Zenfeed:轻量级、高性能的 Golang RSS/Atom 聚合器
在信息碎片化严重的今天,我们习惯于在不同的社交平台、博客和新闻网站之间跳转。RSS(简易信息聚合)作为一种经典的信息订阅方式,依然是获取高质量、无算法干扰内容的最佳手段。
Zenfeed 是一个基于 Golang 开发的开源 Feed 聚合项目。它旨在提供一个简洁、高效且可扩展的后端服务,用于抓取、解析并存储来自 RSS 和 Atom 协议的内容。对于开发者而言,Zenfeed 不仅仅是一个工具,更是一个学习 Golang 并发模型、网络爬虫以及数据持久化的优秀实践案例。
核心特性
1. 高并发抓取引擎
得益于 Golang 原生的 goroutine 和 channel,Zenfeed 能够同时处理数百个 Feed 源而不会造成系统阻塞。它采用了生产者-消费者模型,确保抓取任务在后台高效运行。
2. 标准协议支持
全面支持 RSS 2.0 和 Atom 1.0 协议。通过内置的解析逻辑,它可以将不同格式的 XML 数据统一转化为结构化的 JSON 数据,方便前端调用或第三方集成。
3. 轻量级架构
Zenfeed 摒弃了沉重的企业级框架,采用了极简的依赖管理。这意味着它启动速度极快,内存占用极低,非常适合部署在树莓派(Raspberry Pi)或廉价的 VPS 上。
4. 灵活的存储方案
项目设计了清晰的存储接口,支持将抓取到的文章元数据、正文以及更新状态持久化,避免重复抓取,提高同步效率。
快速上手指南
环境准备
在开始之前,请确保你的系统中已安装: - Go 1.18 或更高版本 - Git
安装步骤
# 克隆项目仓库 git clone https://github.com/glidea/zenfeed.git # 进入项目目录 cd zenfeed # 下载依赖 go mod download # 编译并运行 go run main.go
核心代码逻辑分析
如果你想在自己的项目中借鉴 Zenfeed 的实现,以下是其核心逻辑的简化模拟。
1. 定义 Feed 结构
Zenfeed 首先定义了统一的 Item 结构体,用于抹平不同协议之间的差异。
type FeedItem struct {
Title string `json:"title"`
Link string `json:"link"`
Description string `json:"description"`
PubDate time.Time `json:"pub_date"`
Source string `json:"source"`
}
2. 并发抓取实现
Zenfeed 使用了类似下面的模式来处理多个 URL 的并发请求:
func fetchFeeds(urls []string) {
var wg sync.WaitGroup
results := make(chan FeedItem, len(urls)*10)
for _, url := range urls {
wg.Add(1)
go func(u string) {
defer wg.Done()
items, err := parseRSS(u) // 内部调用 XML 解析逻辑
if err != nil {
log.Printf("Error fetching %s: %v", u, err)
return
}
for _, item := range items {
results <- item
}
}(url)
}
// 启动一个协程关闭 channel
go func() {
wg.Wait()
close(results)
}()
for item := range results {
saveToDB(item) // 持久化存储
}
}
进阶实战:如何扩展 Zenfeed?
如果你想将 Zenfeed 升级为一个商业级或个人定制的阅读器,可以尝试以下扩展方向:
场景 A:增加全文抓取功能
大多数 RSS 源只提供摘要。你可以集成 goquery 库,在获取到 Link 后,再次请求该页面,根据 CSS 选择器提取正文内容。
实现思路:
1. 在 FeedItem 中增加 Content 字段。
2. 编写一个 ExtractFullText(url string) 函数。
3. 在抓取流程中,如果发现 Description 过短,则触发全文抓取。
场景 B:集成推送通知
当某个特定关键词(如 “Golang” 或 “AI”)出现在 Feed 中时,通过 Webhook 发送到飞书、钉钉或 Telegram。
实现思路:
1. 引入一个简单的关键词过滤层。
2. 使用 net/http 发送 POST 请求到第三方 API。
场景 C:构建 RESTful API
为 Zenfeed 增加一个 API 层,让前端(如 Vue 或 React)可以异步获取已抓取的文章。
推荐框架: Gin 或 Echo。
- GET /feeds:获取所有订阅源。
- GET /articles:分页获取所有文章。
- POST /feeds:添加新的订阅地址。
总结与评价
glidea/zenfeed 是一个典型的“小而美”的项目。它没有过度设计,而是专注于解决“抓取 \(\rightarrow\) 解析 \(\rightarrow\) 存储”这个核心链路。
为什么选择 Zenfeed 而不是成熟的 FreshRSS 或 Tiny Tiny RSS? - 可定制性:如果你需要将 Feed 数据集成到自己的 App 中,直接调用 Zenfeed 的后端比通过其他软件的 API 更灵活。 - 性能极致:Go 语言的静态编译和并发特性,使其在处理海量源时比 PHP 或 Python 编写的聚合器具有更高的吞吐量。 - 学习价值:它是学习 Go 语言处理 XML、并发控制和网络 I/O 的绝佳教科书。
无论你是想搭建一个私人的信息过滤网,还是想研究 Golang 的实战应用,Zenfeed 都提供了一个极佳的起点。



还没有评论,来说两句吧...