我想每天少翻几个来源,所以把 GitHub、RSS 和公开网页先收进一个本地日报。
daily-open-source-brief 是我给自己做的每日信息简报工具。
我想解决的问题很具体:每天把公开技术来源整理成一份中文简报,能读、能搜,也能留档。
公开仓库在这里:
https://github.com/GitLaughs/daily-open-source-brief为什么不直接用现成 RSS 邮件工具
传统 RSS 邮件工具很稳定,但我的需求稍微多一点:
- GitHub 仓库需要按 stars、更新时间、topic、语言和活跃度筛选。
- RSS 和公开网页也要进入同一套 item 格式。
- 每天的结果要能写入本地知识库,之后可以搜索、收藏、标记已读。
- 摘要失败时不能整条链路失败,必须能降级成模板日报。
- 邮件和飞书只是发送渠道,不该绑死在主流程里。
所以我没有把它做成“一个脚本里塞满所有逻辑”,而是拆成几个插件阶段。
插件流程
目前我更喜欢这条流水线:
collector -> enricher -> summarizer -> renderer -> sender每一段只做一件事。
collector 负责采集,例如 GitHub Search、RSS、公开网页列表。
enricher 负责去重、打分、补充元数据。
summarizer 负责生成摘要,可以用确定性模板,也可以接外部模型。
renderer 负责输出 HTML、文本和本地归档。
sender 负责投递到邮件或飞书。
这样拆开以后,我临时想加学校公告、GitHub release 或某个技术博客 RSS,只要补一个采集插件,把内容转成统一 item 就行。
小服务器约束
这个项目一开始就按小服务器设计:
- 2 核 CPU。
- 2 GiB 内存。
- 20 GiB 存储。
- 不跑本地大模型。
- 不默认保存完整网页快照。
机器就这么点配置,所以我尽量选轻的东西:SQLite 存数据,FTS5 做全文检索,网页采集先用普通 HTTP 请求。只有确实需要动态渲染时,才上浏览器。
说白了,日报系统不是实时服务,它更像每天运行一次的批处理程序。批处理程序最重要的是稳定、可复跑、失败可解释。
本地知识库
我不希望每天收到一封邮件后,信息就散掉了。
所以简报内容会写入本地 SQLite:
items保存采集条目。repo_snapshots保存 GitHub 仓库快照。digests保存每日简报。mail_logs保存投递结果。
有了这些表,之后就能查某个关键词最近出现过哪些项目,也能看某个仓库是不是反复被推荐过。
这也是它和普通邮件订阅最大的区别:邮件只是发出去的一份结果,SQLite 里留下的历史记录才方便以后翻。
个性化但不串台
日报工具后来加了独立用户画像。每个用户的偏好单独存放,普通聊天上下文不进入日报画像。
这个限制很重要。日报系统只关心“我想看什么技术信息”,不该吸收无关私聊,也不该把某个人的兴趣混到另一个人的简报里。
我的原则是:
preference in, unrelated chat out这会牺牲一点“智能感”,但换来可控性。我宁愿它笨一点,也不希望它悄悄从无关聊天里学偏。
失败降级
日报每天都要跑,不能因为某个环节失败就彻底断掉。
我现在给它留了几条兜底规则:
- GitHub 限流:记录错误,其他来源继续。
- 摘要服务失败:使用模板摘要。
- 邮件发送失败:保留本地 HTML 归档和日志。
- 当天没有高价值内容:固定输出“今日无高价值更新”或跳过发送。
这类自动化麻烦的地方在后面:跑一个月以后,还得看得懂它每天为什么这么做。
下一步
后面我更想先改信息质量,而不是继续加入口:
- 增加仓库 star 增长趋势。
- 增加 release 重要性判断。
- 给公开网页写更稳定的 selector。
- 把收藏、已读和关键词反馈用回到打分里。
- 把日报里的高价值条目转成博客候选。
如果当天真有值得继续追的项目,我就先把它留在本地知识库里。后面有时间,再挑几条写成博客草稿。
说到底,我做这个工具只是想少一点临时翻链接,多一点能回头查的记录。
继续读