多源新闻聚合引擎:18 个源 → 三级去重 → 配额排序 → LLM 解读 → 定时推送。
基于 OpenClaw 运行,支持飞书、Telegram、Discord、Slack 等多渠道推送。
灵感来源于 LearnPrompt/ai-news-radar,在其基础上重新设计了架构。
- 18 个新闻源:覆盖 AI/科技、国内时政、国际大事、财经政策、社交热搜
- 三级去重:L1 URL 归一化 → L2 标题相似度(trigram Jaccard 预过滤 + SequenceMatcher)→ L3 事件聚类
- 配额制推送:权威媒体优先(Tier 1),AI 垂直补充(Tier 2),热搜/滚动填满(Tier 3)
- 双管线:
- ⚡ 快讯速览(12 源):每天 6 次,Top 10 + LLM 读原文生成解读
- 📖 深度精选(6 源):每天 1 次,精选 3-8 条 + 核心观点 + 推荐理由
- 并发抓取:ThreadPoolExecutor,12 源 ~3 秒
- Circuit Breaker:连续 5 次失败自动熔断 1 小时,冷却后自动恢复
- 原子写 state:tmp + rename,防止写入中断导致数据丢失
- 推送日志:JSONL 格式记录每次推送的去重/过滤决策
- 纯 Python,零外部服务依赖:不需要数据库、Redis 或 API key
18个源 → collect.py(并发抓取 → L1/L2 去重 → L3 聚类 → 配额排序)
↓
data/latest_fast.json
↓
OpenClaw Cron (isolated session)
↓
LLM 读原文 → 生成解读
↓
message tool → 飞书/Telegram/...
| 类型 | 源 | Tier | 说明 |
|---|---|---|---|
| 权威时政 | 澎湃新闻 | 1 | HTML scrape |
| 权威时政 | BBC中文 | 1 | HTML scrape |
| 权威时政 | 联合早报 | 1 | HTML scrape |
| 权威时政 | 新华社 | 1 | Homepage scrape |
| 权威财经 | 第一财经 | 1 | HTML scrape |
| 权威财经 | 界面新闻 | 1 | HTML scrape |
| 财经快讯 | 财联社电报 | 1 | RSS |
| 国际快讯 | BBC Breaking | 1 | RSS |
| AI 垂直 | 36kr AI | 2 | HTML scrape |
| 热搜/滚动 | 头条热榜 | 3 | JSON API |
| 热搜/滚动 | 新浪滚动 | 3 | JSON API |
| 社交热搜 | 微博热搜 | 3 | Ajax API |
| 类型 | 源 | 说明 |
|---|---|---|
| AI 深度 | 数字生命卡兹克 | 搜狐号 JSON API |
| AI 深度 | 量子位 | 搜狐号 JSON API |
| 自媒体 | 刘润 | 搜狐号 JSON API |
| AI 官方 | OpenAI Blog | RSS |
| AI 官方 | HuggingFace Blog | RSS |
| 国际财经 | FT中文网 | RSS |
- Python 3.11+
- OpenClaw(用于 LLM 解读 + 定时推送)
git clone https://github.com/kylefu8/openclaw-news-digest.git
cd openclaw-news-digest
bash setup.shsource .venv/bin/activate
# 快讯源 Top 5
python collect.py --flow fast --max-items 5 --format text
# 深度源
python collect.py --flow deep --format text
# JSON 输出(cron job 使用此格式)
python collect.py --flow fast --format json --output data/latest_fast.json --state-dir data --mark-pushed这个项目本身就是为 OpenClaw 设计的。最简单的方式是直接告诉你的 OpenClaw 助手:
我 clone 了 openclaw-news-digest 项目到 ~/openclaw-news-digest,帮我装一下。
OpenClaw 会自动读取 SETUP_GUIDE.md,按步骤完成安装、验证抓取、创建 cron job 并配置推送目标。
你也可以让它帮你定制:
- 帮我加一个 RSS 源:https://example.com/feed.xml,放到快讯流
- 把快讯从每天 6 次改成每天 3 次(9/13/18 点)
- 把 Tier 1 配额从 7 条改成 5 条
- 帮我加一个搜狐号,作者 ID 是 123456
OpenClaw 会直接修改 config.yaml 和 cron job 配置,不需要你手动编辑文件。
cron_templates/ 目录下有两个 cron job 模板:
-
编辑模板,替换占位符:
{{WORKSPACE}}→ 项目绝对路径(如/home/user/openclaw-news-digest){{CHANNEL}}→ 推送渠道(feishu/telegram/discord/slack){{TARGET}}→ 推送目标(如user:ou_xxx或chat:xxx)
-
通过 OpenClaw 导入:
openclaw cron add --file cron_templates/fast_news.json openclaw cron add --file cron_templates/deep_digest.json
所有配置集中在 config.yaml,无需改代码。
# config.yaml → sources 下添加
sources:
my_new_source:
name: 我的新源
type: scraper # scraper / rss / sohu_api / json_api
module: fetchers.cn_media
func: fetch_my_source # 对应 Python 函数名
flow: fast # fast(快讯)/ deep(深度)
tier: 2 # 1=优先 2=补充 3=填满四种源类型:
scraper:HTML 页面解析,需要写对应的 fetch 函数rss:RSS/Atom 订阅,只需填feed_url(+ 可选fallback_urls)sohu_api:搜狐号 JSON API,只需填author_idjson_api:头条/新浪等 JSON 接口,需要写对应的 fetch 函数
最简方式——添加 RSS 源(零代码):
my_rss_source:
name: 某某博客
type: rss
module: fetchers.rss
func: fetch_rss
flow: deep
feed_url: https://example.com/feed.xml
fallback_urls: # 可选:主 URL 失败时的备用
- https://mirror.example.com/feed.xml添加搜狐号(零代码):
mp_someone:
name: 某搜狐号
type: sohu_api
module: fetchers.sohu
func: fetch_sohu_author
flow: deep
author_id: "123456" # 搜狐号作者 ID添加自定义 scraper:
- 在
fetchers/中写函数,签名def fetch_xxx(session, *, site_id, site_name, timeout) -> list[NewsItem] - 在 config.yaml 中注册
删除源:直接删掉对应的 yaml 条目即可。
quota:
fast:
max_items: 10 # 每轮推送条数(改为 15 就推 15 条)
tiers:
1: { max: 7, label: "权威媒体" } # Tier 1 最多占 7 条
2: { max: 3, label: "AI垂直" } # Tier 2 最多占 3 条
3: { fill: true, label: "热搜/滚动" } # Tier 3 补满剩余
deep:
max_items: 20 # 深度候选池大小(LLM 从中精选 3-8 条)dedup:
l2_title_similarity: 0.7 # 标题相似度阈值(调低=更激进去重)
l2_max_items: 500 # L2 安全阀(防止 O(n²) 过慢)
l3_cluster_similarity: 0.55 # 事件聚类阈值(调低=更多新闻被合并)
l2_priority_sources: # 去重冲突时优先保留这些源
- xinhua
- thepaper
- bbc_cnfetch:
timeout_connect: 15 # 连接超时(秒)
timeout_read: 45 # 读取超时(秒)
socket_timeout: 60 # Socket 超时(秒)
user_agent: "Mozilla/5.0 ..." # 自定义 UAstate:
ttl_days: 7 # 推送记录保留天数(超期自动清理,避免 state 文件膨胀)通过 --max-age 参数控制只推送最近 N 天的文章,防止 RSS 源或 API 返回过旧内容:
# 快讯:只要最近 2 天(快讯源几乎都是当天内容,2 天防跨午夜丢失)
python collect.py --flow fast --max-age 2
# 深度:最近 7 天(博客/长文更新频率低,7 天覆盖一周精华)
python collect.py --flow deep --max-age 7推荐值:快讯 --max-age 2,深度 --max-age 7。
push:
fast:
schedule: "0 7,10,12,15,18,21 * * *" # cron 表达式
timezone: Asia/Shanghai
deep:
schedule: "0 20 * * *"
timezone: Asia/Shanghai修改后需同步更新 OpenClaw cron job 的 schedule(config.yaml 中的 push 配置仅作参考记录,实际调度由 OpenClaw cron 控制)。
# 检查是否有 ≥4 家媒体同时报道的事件
python collect.py --flow fast --check-breaking --breaking-threshold 4可集成到 OpenClaw heartbeat 中,实现突发事件即时推送。
编辑 ranking.py 中的 score_item() 函数:
# 当前公式
score = multi_source_count * 3 + tier_weight * 2 + freshness编辑 health.py 中的常量:
CB_THRESHOLD = 5 # 连续失败次数触发熔断
CB_COOLDOWN = 3600 # 熔断冷却时间(秒,默认 1 小时)python collect.py [OPTIONS]
Options:
--flow {fast,deep} 选择管线(默认:全部)
--format {text,json} 输出格式(默认:text)
--max-items N 最大输出条数
--max-age N 只保留最近 N 天的文章(0=不限,推荐:快讯 2,深度 7)
--output PATH JSON 输出文件路径
--state-dir DIR 状态文件目录(用于去重已推送内容)
--mark-pushed 标记输出的条目为已推送
--check-breaking 检查是否有突发事件(multi_source ≥ 4)
--breaking-threshold N 突发事件阈值(默认 4)
-v, --verbose Debug 日志
| 层级 | 方法 | 阈值 | 说明 |
|---|---|---|---|
| L1 | URL 归一化 | 精确匹配 | 去 tracking 参数、统一协议 |
| L2 | 标题相似度 | >0.7 | trigram Jaccard 预过滤(减少 99.97% 的 SequenceMatcher 调用) |
| L3 | 事件聚类 | >0.55 | UnionFind 聚类,合并同一事件的不同报道 |
冲突时优先保留 Tier 值更小(更权威)的源。
| 层级 | 说明 | 默认上限 |
|---|---|---|
| Tier 1 | 权威媒体 | 7 条 |
| Tier 2 | AI 垂直 | 3 条 |
| Tier 3 | 热搜/滚动 | 补满至 10 |
importance 排序公式:multi_source_count × 3 + tier_weight × 2 + freshness
openclaw-news-digest/
├── config.yaml # 源/配额/去重/调度 集中配置
├── setup.sh # 一键安装脚本
├── pyproject.toml # 依赖声明 + 工具配置
├── requirements.txt # pip 依赖
├── collect.py # 主入口:抓取 → 去重 → 排序 → 输出
├── dedup.py # 三级去重(L1 URL + L2 标题 + L3 聚类)
├── ranking.py # importance 评分 + 配额分配
├── health.py # 源健康追踪 + Circuit Breaker
├── state.py # 推送状态管理(原子写)
├── push_log.py # 推送日志(JSONL)
├── fetchers/
│ ├── __init__.py
│ ├── common.py # NewsItem 数据结构 + 工具函数
│ ├── cn_media.py # 中文媒体抓取器(12 个函数)
│ ├── rss.py # 通用 RSS/Atom 解析
│ └── sohu.py # 搜狐号 JSON API
├── cron_templates/ # OpenClaw cron job 模板
│ ├── fast_news.json # 快讯速览模板
│ └── deep_digest.json # 深度精选模板
├── tests/ # 100 个测试,pytest
│ ├── test_common.py
│ ├── test_config.py
│ ├── test_dedup.py
│ ├── test_health.py
│ ├── test_integration.py
│ ├── test_new_sources.py
│ ├── test_ranking.py
│ └── test_state.py
├── .github/workflows/
│ └── test.yml # CI: Python 3.11/3.12/3.13
├── .pre-commit-config.yaml # Ruff + Mypy hooks
└── data/ # 运行时数据(gitignore)
├── .state.fast.json
├── .state.deep.json
├── source_health.json
└── push_log.jsonl
# 安装开发依赖
.venv/bin/pip install -e ".[dev]"
# 跑测试
.venv/bin/pytest -v
# Lint + 类型检查
.venv/bin/ruff check .
.venv/bin/mypy .
# Pre-commit hooks
pip install pre-commit
pre-commit installMIT
- LearnPrompt/ai-news-radar — 原始灵感来源
- OpenClaw — AI 助手运行时