Files
atlas/sreweekly-digest/scripts/README.md

129 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# sreweekly.py
SRE Weekly 抓取与文章提取脚本。单文件、无外部服务依赖,专为 n8n 定时任务设计:脚本自身**只负责抓取与落盘**,不发送邮件、不推送通知。
## 功能概览
- 通过 RSS (`https://sreweekly.com/feed/`) 扫描新一期 SRE Weekly
- **回溯抓取历史期刊**(RSS 只暴露最近 ~10 期,`--backfill` 直接走站点 URL 抓任意老期)
- 把每期 `content:encoded` 原样保存为 HTML
- 解析出每期的所有文章条目(标题 / 链接 / 简介 / 引用 / 作者)
- 用 [`trafilatura`](https://github.com/adbar/trafilatura) 抓文章原文并转 Markdown
- 用 `manifest.json` 记录每期状态,避免重复处理
- 每篇文章生成一个独立 `.md` 文件,含 feed 简介 + 抓取的正文
## 安装依赖
```bash
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
```
## 用法
```bash
# 扫描 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` 文件:
```markdown
# 文章标题
- **期号**: 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 到今天——不影响提取,但排序会乱