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 开发与实用工具开发的良好实践。

相关推荐
小码哥_常1 小时前
告别MySQL!大厂集体转投PostgreSQL,到底藏着什么玄机?
后端
刀法如飞2 小时前
Go数组去重的20种实现方式,AI时代解决问题的不同思路
后端·算法·go
AI人工智能+电脑小能手3 小时前
【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别
java·开发语言·后端·面试·代理模式
swipe3 小时前
别再把 AI 聊天做成纯文本:从 agui 这个前后端项目,拆解“可感知工具调用”的流式 AI UI
后端·langchain·llm
GetcharZp3 小时前
GitHub 爆火!纯 Go 编写的文件同步神器 Syncthing,凭什么成为程序员的标配?
后端
hERS EOUS3 小时前
SpringBoot 使用 spring.profiles.active 来区分不同环境配置
spring boot·后端·spring
LucianaiB3 小时前
我用飞书多维表做了一个 AI 活动推荐智能体:每天自动催我别错过截止日期!
后端
铁皮饭盒4 小时前
第2课:5分钟!用 Trae AI 生成你的第一个后端服务(Bunjs + Elysia)
前端·后端·全栈
金銀銅鐵4 小时前
[git] 浅解 git reset 命令
git·后端