Go语言实战案例-项目实战篇:新闻聚合工具

在信息爆炸的时代,用户往往需要从多个渠道获取新闻。一个新闻聚合工具 能够帮助我们自动化收集、分类和展示新闻,从而节省时间并提升阅读效率。本文将带你用 Go 语言实现一个简易的新闻聚合器,从多个 RSS 源抓取新闻并展示到网页端。


功能目标

  1. 数据采集

    • 从多个新闻源(RSS/Atom)抓取新闻标题、链接、发布时间。
  2. 数据聚合

    • 将不同来源的新闻合并,按时间排序。
  3. 数据展示

    • 提供一个 Web 页面,列出最新新闻。
  4. 扩展性

    • 可轻松添加新的新闻源。

技术栈

  • Go 标准库net/httphtml/template
  • RSS/Atom 解析mmcdole/gofeed
  • 并发采集:goroutine + channel

项目结构

go 复制代码
news-aggregator/
├── main.go
├── templates/
│   └── index.html
├── go.mod

核心代码(main.go)

go 复制代码
package main

import (
	"html/template"
	"log"
	"net/http"
	"sort"
	"time"

	"github.com/mmcdole/gofeed"
)

// 新闻结构体
type NewsItem struct {
	Title string
	Link  string
	Date  time.Time
	Source string
}

// 聚合器
type Aggregator struct {
	feeds []string
	items []NewsItem
}

func NewAggregator(sources []string) *Aggregator {
	return &Aggregator{feeds: sources}
}

// 抓取新闻
func (a *Aggregator) Fetch() {
	parser := gofeed.NewParser()
	var allItems []NewsItem

	for _, url := range a.feeds {
		feed, err := parser.ParseURL(url)
		if err != nil {
			log.Println("❌ 获取失败:", url, err)
			continue
		}
		for _, item := range feed.Items {
			pub := time.Now()
			if item.PublishedParsed != nil {
				pub = *item.PublishedParsed
			}
			allItems = append(allItems, NewsItem{
				Title:  item.Title,
				Link:   item.Link,
				Date:   pub,
				Source: feed.Title,
			})
		}
	}

	// 按时间排序
	sort.Slice(allItems, func(i, j int) bool {
		return allItems[i].Date.After(allItems[j].Date)
	})

	a.items = allItems
}

// 启动 Web 服务
func (a *Aggregator) Serve() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		tpl := template.Must(template.ParseFiles("templates/index.html"))
		tpl.Execute(w, a.items)
	})
	log.Println("✅ 新闻聚合服务启动: http://localhost:8080")
	http.ListenAndServe(":8080", nil)
}

func main() {
	// 新闻源
	sources := []string{
		"https://rss.sina.com.cn/news/china/focus15.xml",
		"http://feeds.bbci.co.uk/news/rss.xml",
		"https://rss.nytimes.com/services/xml/rss/nyt/World.xml",
	}

	agg := NewAggregator(sources)

	// 定时抓取
	go func() {
		for {
			agg.Fetch()
			time.Sleep(10 * time.Minute)
		}
	}()

	// 启动 Web 展示
	agg.Serve()
}

模板文件(templates/index.html)

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>新闻聚合工具</title>
</head>
<body>
  <h1>最新新闻</h1>
  <ul>
    {{range .}}
    <li>
      <a href="{{.Link}}" target="_blank">{{.Title}}</a>
      <small>({{.Source}} - {{.Date.Format "2006-01-02 15:04"}})</small>
    </li>
    {{end}}
  </ul>
</body>
</html>

使用方法

  1. 初始化项目并安装依赖:
bash 复制代码
go mod init news-aggregator
go get github.com/mmcdole/gofeed
  1. 运行:
bash 复制代码
go run main.go
  1. 浏览器访问 http://localhost:8080,即可查看最新新闻。

扩展功能

  1. 搜索功能:支持按关键词过滤新闻
  2. 分类展示:按来源或主题分组
  3. 存储与历史记录:将新闻保存到数据库(SQLite/MySQL)
  4. 推送功能:结合邮件/微信/钉钉推送最新新闻
  5. 前端美化:结合 Vue/React 优化界面

总结

通过本案例,我们实现了一个简易的新闻聚合工具 :能够从多个 RSS 源抓取新闻,按时间排序,并通过 Web 页面展示。项目中涵盖了HTTP 请求、RSS 解析、定时任务、模板渲染等常见技能,是 Go Web 开发与实用工具开发的良好实践。

相关推荐
晓杰'几秒前
从0到1实现Balatro游戏后端(5):得分计算与单局结算流程实现
后端·typescript·node.js·游戏开发·项目实战·nestjs·webscoket
减瓦16 分钟前
Jackson 自定义反序列化器的类型不匹配陷阱
java·后端
HLAIA光子18 分钟前
计网面试躲不掉的三连问:OSI七层、HTTPS握手、REST还是RPC
后端·网络协议
JAVA社区22 分钟前
Java高级全套教程(九)—— SpringCloud超详细实战详解
java·开发语言·后端·spring cloud·面试·职场和发展
yspwf24 分钟前
Electron/Node 本地集成 C#/.NET,node-api-dotnet
后端
万少34 分钟前
Claude Code 任务结束会自己喊你:一个 Stop Hook 搞定提示音
前端·后端·代码规范
仙俊红43 分钟前
spring有多个对象时如何注入
java·后端·spring
Java爱好狂.1 小时前
Redis高级笔记:深入浅出Java面试高频考点!
java·数据库·redis·后端·java面试·java程序员·java八股文
IT_陈寒1 小时前
React hooks闭包陷阱把我坑惨了,原来这才是正确用法
前端·人工智能·后端
会编程的土豆1 小时前
Go 里 interface 为什么能比较?到底在比什么?
开发语言·后端·golang