Files
atlas/sreweekly-digest/scripts

sreweekly.py

SRE Weekly 抓取与文章提取脚本。单文件、无外部服务依赖,专为 n8n 定时任务设计:脚本自身只负责抓取与落盘,不发送邮件、不推送通知。

功能概览

  • 通过 RSS (https://sreweekly.com/feed/) 扫描新一期 SRE Weekly
  • 回溯抓取历史期刊(RSS 只暴露最近 ~10 期,--backfill 直接走站点 URL 抓任意老期)
  • 把每期 content:encoded 原样保存为 HTML
  • 解析出每期的所有文章条目(标题 / 链接 / 简介 / 引用 / 作者)
  • 用 trafilatura 抓文章原文并转 Markdown
  • 用 manifest.json 记录每期状态,避免重复处理
  • 每篇文章生成一个独立 .md 文件,含 feed 简介 + 抓取的正文

安装依赖

pip3 install feedparser trafilatura

trafilatura 仅在抓文章正文时才必需;若加 --skip-fetch 只用 feed 简介,可省略。

目录结构

默认工作目录 ~/Workspace/nexus/sreweekly/(可用 --dir 覆盖):

sreweekly/
├── manifest.json               # 状态记录
├── html/<id>-<日期>.html       # 每期原始 HTML(feed 版 或 backfill 站点整页)
├── pages/<id>.html             # backfill 抓到的站点整页缓存
├── articles/<id>/              # 每篇文章原始 HTML 缓存 + index.json 抓取日志
│   ├── 01-<slug>.html
│   └── index.json
└── markdown/<id>/              # 每期文章的 markdown 输出
    ├── 01-<slug>.md
    └── 02-<slug>.md

用法

# 扫描 feed,新增期落盘并登记 manifest
python3 sreweekly.py

# 只探测有无新期(供 n8n 分支判断),输出 NEW:533,532 或 NONE
python3 sreweekly.py --check

# 提取指定期文章为 markdown(默认联网抓正文)
python3 sreweekly.py --extract 533
python3 sreweekly.py --extract 433..464    # 期号区间(缺失的期告警跳过,不阻断)
python3 sreweekly.py --extract latest      # 最新一期
python3 sreweekly.py --extract pending     # 所有未提取的期(n8n 每日推荐)
python3 sreweekly.py --extract all         # 全部(配合 --force 覆盖)

# 查看状态
python3 sreweekly.py --status
python3 sreweekly.py --issues

# 回溯抓取历史期刊(绕过 RSS 只有最近 ~10 期的限制)
python3 sreweekly.py --backfill 430..533     # 抓期号 430 到 533 之间所有未登记的期
python3 sreweekly.py --backfill 1..533       # 全站回溯(500+ 期,约 12-15 分钟)
python3 sreweekly.py --backfill 450          # 只抓单期
# 回溯完再走标准提取流程:
python3 sreweekly.py --extract pending
# 或只提取回溯的那段区间:
python3 sreweekly.py --extract 430..533

选项

选项 说明
--feed URL RSS 地址,默认 https://sreweekly.com/feed/
--dir PATH 工作目录,默认 ~/Workspace/nexus/sreweekly/
--force 重新提取已提取过的期,覆盖旧 markdown
--skip-fetch 不抓文章正文,只使用 feed 简介
--force-fetch 忽略 articles/ / pages/ 本地缓存,重新联网抓 HTML
--sleep 秒数 每次抓取间隔(默认 1.5,--backfill 也遵守此参数)

典型 n8n 流程

  1. Cron 触发 → python3 sreweekly.py --check
  2. 判断输出:NEW:... 走后续,NONE 结束
  3. python3 sreweekly.py(扫描落盘新期)
  4. python3 sreweekly.py --extract pending(抓正文 + 生成 markdown)
  5. 下游节点读取 markdown/<id>/*.md 汇总成邮件/推送

Markdown 输出示例

每篇文章一个 .md 文件:

# 文章标题

- **期号**: SRE Weekly Issue #533(2024-05-20)
- **作者**: Jane Doe
- **链接**: https://example.com/post

## 简介
(来自 feed 的原始描述与引用)

## 正文
(trafilatura 抽取的原文 markdown;失败时显示错误信息)

Manifest 字段

manifest.json 中每期条目字段:

字段 含义
id / title / url / pub_date 期号、标题、原文链接、发布日期
html_file 落盘 HTML 相对路径
fetched_at / extracted_at 抓取与提取时间戳
extracted 是否已提取为 markdown
article_count 该期文章数
markdown_dir markdown 输出目录(相对)
articles_fetched / articles_failed 正文抓取成功/失败数
source 数据来源标记:backfill 表示由 --backfill 从站点整页抓取(feed 抓取无此字段)

故障排查

  • feed 抓取失败或为空:检查 --feed 网络可达性,或 feed 结构变更
  • trafilatura returned empty:某些站点反爬/JS 渲染,正文段落会写入错误提示但不影响其它文章
  • 重跑某期:--extract <id> --force;重新联网抓正文再加 --force-fetch
  • 回溯抓不到某期:脚本会打印 ⚠️ #<id> 抓取失败:... 并继续下一期,最后汇总失败期号;对失败期号单独 --backfill <id> --force-fetch 重试即可
  • 回溯抓到的期日期显示当天:说明页面 <a class="updated"> 结构变了,extract_pub_date_from_page 未命中,会 fallback 到今天——不影响提取,但排序会乱