这个 skill 负责什么
把“给我一个公众号文章链接,然后批量抓取这个公众号最近 N 篇文章并落盘”这件事标准化。
这个 skill 自带抓取脚本包,默认使用当前 skill 目录里的这些文件:
./scripts/main.py./scripts/requirements.txt./scripts/config.json./scripts/run_fetcher.sh./scripts/run.command./references/抓取器说明.md
./scripts/main.py 是抓取主程序。./scripts/run_fetcher.sh 是 agent 更适合调用的启动脚本,会在 scripts/ 目录下缺少 .venv 时自动创建并安装依赖。需要看工具细节、安装方式、JSON 返回和缓存目录时,再读 ./references/抓取器说明.md。
下面这些情况不要硬用本 skill:
- 用户只要单篇文章摘要,不需要批量抓取
- 用户要做最终排版、发布、审查
- 用户要抓评论数、阅读数、点赞数等额外指标
- 用户要求云端缓存公众号登录态
你依赖的本地工具能力
当前抓取工具已经具备这些能力:
- 本地保存登录态,不走云端
- 登录失效时自动生成二维码
- 支持
CLI + JSON - 支持
ensure-login - 支持
login-status - 支持
fetch - 支持
fetch --resume <上一轮articles.json>(续抓,跨轮去重,不重复) - 支持
fetch --since/--until <YYYY-MM-DD>(时间窗,跳过过期/过时旧文,按中国时区 Asia/Shanghai 零点对齐) - 支持
fetch --dry-run(只返回将要抓取的清单,不落盘——配合时间窗做"先预览后决定") - 支持
fetch --force-qr/--login-timeout/--qr-refresh(登录增强) - 支持
fetch --safe/--fast(限流预设:保守 / 激进) - 支持
fetch --md-only(只输出 Markdown,不生成 HTML;也可在config.json设write_html:false作为永久默认) - 支持
fetch --limit N(本轮最多抓 N 篇新文章,覆盖config.article_limit;如"只要最新 10 篇"直接--limit 10) - 支持
fetch --stop-after-seen N(增量早停:翻页时连续遇到 N 篇已抓文章即提前停止,避免为找增量翻完全部历史;带--resume/increment时默认 30,设 0 禁用) - 支持
status(抓取前速览:各账号上次抓到哪天、文章数、登录态,落实"先查上轮再抓"习惯) - 支持
album(抓取公众号文章合集 / 专辑:直接给appmsgalbum合集链接,复用登录态拉取合集内全部文章,无需单篇种子翻历史;输出与 fetch 一致的 Markdown) - 去重增强:每轮在输出目录生成
seen_urls.json清单,跨轮 / 跨次运行自动跳过已抓文章;失败的会重试,已下载的 Markdown 幂等复用 - 限流保护:后台 API 调用与文章下载均插入「固定间隔 + 随机抖动」,遇
429/5xx/ "操作频繁" 自动指数退避 - 支持
clear-login - 支持
increment(增量续抓:自动定位上次 output 目录、复用登录态、跳过已抓文章,公众号未来更新时一行命令搞定,绝不重复) - 支持
status(抓取前速览:遍历output_root下各账号目录,汇总文章数、最新发布日期、登录态,落实"先查上轮再抓"习惯,避免重复劳动) - 输出
Markdown、HTML、articles.json(用--md-only或config.json的write_html:false可只出 Markdown)
这个 skill 默认调用当前目录内自带的抓取器副本,不要回头依赖桌面上的原项目路径,除非用户明确要求你同步或升级那份原始项目。
运行前检查
先检查以下文件是否存在:
./scripts/main.py./scripts/requirements.txt./scripts/run_fetcher.sh
如果缺失:
- 明确告诉用户 skill 自带抓取器不完整。
- 不要伪造抓取结果。
- 如果用户要你补安装,再在当前 skill 目录里补齐。
输入约定
最小输入通常只需要:
- 任意一篇目标公众号文章链接
可选输入:
- 单次抓取篇数
- 输出父目录
- 是否需要清空已有登录态后重登
- 当前环境是
IM、纯终端、还是有桌面界面
如果用户没有显式给抓取篇数和输出目录:
- 优先沿用
./scripts/config.json - 不要擅自改
./scripts/main.py - 需要调数量或输出路径时,只改
./scripts/config.json
配置规则
工具当前通过 ./scripts/config.json 控制这些参数:
output_parentoutput_folder_namearticle_limitconcurrencydisplay_modewrite_html(是否同时生成 HTML 文件,true默认;设为false则只出 Markdown)
处理原则:
- 用户明确要求改输出目录或抓取篇数时,只改
./scripts/config.json - 用户没要求时,沿用现有配置
- Linux / agent / IM 场景优先用
display_mode = "silent" - 纯终端扫码场景优先用
display_mode = "terminal" - 本机桌面人工扫码场景可用
display_mode = "image"
推荐直接调用:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh <subcommand> ...
标准工作流
1. 确认是否要清除登录态
默认不要清。
只有用户明确说:
- “删掉登录状态重新来”
- “我要测试从零登录”
- “我要把机器交给别人,先清缓存”
才执行:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh clear-login --json
2. 选择二维码展示模式
按场景选:
- IM / bot / agent 回消息:
silent - Linux 纯终端:
terminal - 本机有图形界面,用户直接扫码:
image - 不确定但有人机混合:
auto
3. 确保登录可用
优先运行:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh ensure-login --json --display silent
如果返回 authenticated,直接继续。
登录增强:加
--force-qr可忽略本地已缓存的登录态、强制重新扫码(用于缓存过期却没自动识别的场景);--login-timeout(默认 1800s)控制二维码等待上限,--qr-refresh(默认 90s)控制二维码刷新间隔。微信二维码单码有效期约 90–120s,务必只扫当前弹出的最新活码,扫到旧码会一直waiting_scan。
如果返回 waiting_scan:
- 读取
qr_png_path和qr_text_path - IM / 聊天场景:优先把
qr_png_path对应的图片发给用户 - 纯终端场景:打印或转述
qr_text_path - 本机桌面场景:如果当前命令不是
--display image,可以改为--display image重新启动登录 - 然后轮询:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh login-status --json
直到出现:
status = authenticated- 或
status = timeout - 或用户中止
4. 执行抓取
登录成功后,执行:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh fetch "公众号文章链接" --json --display silent
抓取成功时会返回:
account_nameaccount_aliasdownloadedfailedoutput_dirindex_fileresults
4.5 续抓模式(--resume):抓超过 200 篇且不重复
单号硬上限为 article_limit(默认 200)篇。要抓“接下来”的文章且零重复,用 --resume 指向上一轮的 articles.json:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh fetch "公众号文章链接" --json --display silent \
--resume "<上一轮输出目录>/articles.json"
续抓行为:
- 读取上一轮
articles.json里的文章链接作为“已抓清单”,本轮自动跳过,实现跨轮去重 - 复用同一输出目录(不新建时间戳文件夹),新文章续写进
markdown/、文件名序号从已有.md数 +1 起,不会覆盖 - 续抓只写 Markdown,不生成
html/ - 新结果合并进同一
articles.json,累计篇数一目了然 - 轮到没有新文章时返回 0 篇,即该号历史已抓完
原理是链接去重而非硬算偏移(偏移在批次/多图文下会错位),所以放心一路 --resume 接力即可。
4.6 时间窗(--since / --until):跳过过期/过时旧文
微信接口最新文章在最前。加时间窗后,遇到比 --since 更老的文章会立即停(后面全是更老的);--until 丢弃比某天更新的文章(含当天,极少用)。
# 只抓 2024-07-08 之后(近2年),且跳过已抓
python main.py fetch "公众号文章链接" --json --since 2024-07-08 --resume "<上一轮输出目录>/articles.json"
# 只抓 2025 全年
python main.py fetch "公众号文章链接" --json --since 2025-01-01 --until 2025-12-31
# 先预览(不下载)近 2 年清单,确认无误再去掉 --dry-run 真抓
python main.py fetch "公众号文章链接" --json --since 2024-07-08 --dry-run
--since YYYY-MM-DD:只保留发布时间 ≥ 该日期(比这老的跳过/停)——主要用去丢弃过期、内容过时、链接失效的旧文--until YYYY-MM-DD:只保留发布时间 ≤ 该日期(含当天)- 时区对齐(已修正):默认按 中国时区
Asia/Shanghai(UTC+8)零点对齐。微信create_time是 UTC 秒,本工具会换算成"中国当天 0 点"再比较,避免旧版按 UTC 零点导致差一天的问题(例如 2024-07-08 07:09 的中国文章,旧版会被误判为"旧文",新版正确归为"新文")。 - 若需按世界时对齐,加
--tz UTC。 - 可与
--resume、--dry-run组合使用。
4.7 预览模式(--dry-run):先清单、后抓取
带 --dry-run 时,工具仍会登录并查询文章列表、应用时间窗与去重,但不下载任何文件,只返回 would_download 清单(含标题、链接、发布时间、已抓取标记)。非常适合"先看看会抓哪些,再决定要不要真落盘 / 删旧文"的工作流。
4.8 限流保护(避免触发公众号封禁)
为防止短时间内大量请求被腾讯识别为爬虫、触发限流 / 封号,工具在每一层都加了保护:
- 后台 API(
searchbiz/appmsgpublish):每次调用前插入api_min_delay + 随机抖动的间隔(默认 ≈2.0+1.5s)。 - 文章下载:每篇之间插入
dl_min_delay + 随机抖动(默认 ≈1.5+1.2s),并发默认降到 3 路(旧版是 6)。 - 自动退避:遇到
429/5xx/ 接口返回"操作频繁 / 频率"等,按backoff_base × 2^n指数退避后重试(默认最多 6 次)。 - 预设切换:
--safe:保守模式,间隔加大、并发降到 2,速度最慢但最稳。--fast:激进模式,间隔减小、并发拉到 5,速度最快但更易触发限流(风险自担)。- 也可用
--min-delay/--max-jitter精细覆盖下载间隔。
- 这些参数都写在
config.json的throttle字段里,可长期调。
4.9 不重复抓取(去重增强)
- 跨轮续抓:
--resume读取上一轮articles.json,只跳过其中 status=ok 的文章;失败的不会进清单,下一轮会被重试。 - 跨次清单:每轮在输出目录写
seen_urls.json,记录所有已成功下载的归一化链接。即便不传--resume,再次对同目录抓取也会自动跳过已抓文章。 - 幂等复用:下载前若发现对应 Markdown 已存在且非空,直接复用,不再发请求。
- 归一化:按
__biz/mid/idx/sn归一化链接,忽略chksm/scene等无关参数与参数顺序,避免“同一篇被判成两篇”。
4.10 增量续抓(increment):公众号未来更新,零重复一行搞定
首次完整抓取后,公众号今后每次发文,都不用重新跑全量、也不用记路径和日期。直接:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh increment --url "任意一篇该号文章链接" --json --display silent
它会自动做三件事:
- 在
output_root(config 的output_parent/output_folder_name)下找最新的含articles.json的抓取目录(即上次的结果); - 用上一轮的
articles.json作为“已抓清单”(--resume等价物),翻页时跳过全部已抓文章,新发的必然不在清单里,会被抓到; - 复用同一输出目录,新文章续写进
markdown/、合并进同一个articles.json。
行为要点:
- 默认增量早停(安全):翻页时若连续遇到
stop_after_seen(默认 30)篇已抓文章,即判定已抵达"已抓边界"提前停止——既避免为找增量翻完全部历史(之前无早停时"最新 10 篇"也要翻 6 分多钟),又因 30 篇安全余量绝不漏抓新文章,且不依赖旧articles.json是否带发布时间字段。可用--stop-after-seen 0彻底禁用早停(翻到列表尽头)。 - 若想进一步提速,可显式加
--since YYYY-MM-DD做早停;但--since不能晚于"已抓最新文章的发布日",否则翻页会提前停、漏掉中间的新文章。不确定就别加。 - 可用
--limit N限制本轮最多抓 N 篇新文章(覆盖config.article_limit)。例如"只要最新 10 篇":increment --url "<种子>" --limit 10。 - 可加
--dry-run先预览“将新增哪几篇”(不落盘),确认后再真抓。 - 可加
--last-dir "<指定output目录>"强制指定上次目录(多号混抓、想精确控制时用)。 increment同样遵循config.json的write_html(及临时--md-only):若已设为只出 Markdown,增量续抓也只写 Markdown,不会补生成 HTML。- 若上次之后公众号没更新,不会报错,而是返回
status = up_to_date(“没有比上次更新的文章,无需抓取”)。 - 仍支持
--safe/--fast/--force-qr/--login-timeout/--qr-refresh等全部选项。
与手动
fetch --resume "<上次>/articles.json"完全等价,但省去了"记住上次路径 + 记住上次日期"的认知负担。种子链接仍用--url或位置参数传入,仅用于定位公众号。
4.11 status 子命令(抓前看上轮状态)
在决定"要不要抓、抓多少、从哪天起"之前,先跑 status 速览历史成果,避免重复劳动或盲目翻页:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh status --json
它会:
- 遍历
output_root(config 的output_parent/output_folder_name)下所有含articles.json的抓取目录,逐个统计:account:公众号名total/ok:articles.json里总条数、下载成功条数latest_publish:最新一篇的发布日期(中国时区),以及对应的标题output_dir:该账号结果目录
- 调
login-status取当前登录态(authenticated/waiting_scan/timeout),让你知道这一轮要不要先扫码。
返回结构(JSON 模式):
{
"status": "ok",
"output_root": "<...>/输出文章",
"login": { "status": "authenticated", "...": "..." },
"runs": [
{
"account": "跨境AI入门指南",
"total": 192, "ok": 192,
"latest_publish": "2026-07-10 21:33",
"latest_title": "xxx",
"output_dir": "<...>/跨境AI入门指南_20260711_110004"
}
]
}
人类可读模式会直接打印每个账号一行摘要 + 登录态。典型用法:
- 抓前先看:
status→ 看"上次抓到哪天" → 用--since <那天>或increment续抓,绝不重复。 - 判断要不要扫二维码:
status的login.status若已是authenticated,直接抓;若是waiting_scan才发起ensure-login。 - 可与
--quiet组合,仅在登录态失效或某账号 0 篇时输出,适合塞进自动化前的自检。
4.12 album 子命令(抓取公众号合集 / 专辑)
当用户给出的是公众号文章合集页(mp.weixin.qq.com/mp/appmsgalbum?__biz=...&album_id=...,常见于"合集""目录""系列课"入口),而不是某一篇文章时,用 album 子命令,而不是 fetch:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh album "https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzI2NTQ2OTkwMg==&action=getalbum&album_id=4560732506928398340" --json --display silent
# 或:
python main.py album --url "https://mp.weixin.qq.com/mp/appmsgalbum?__biz=...&album_id=..."
要点:
- 无需单篇种子、无需重新扫码:
album复用ensure-login留下的登录态 cookie,直接调用读者端appmsgalbum接口拿到合集内全部文章列表,再逐篇抓取正文。 - 自动翻页:合集文章按页返回(每页 10 篇),
album自动翻到continue_flag=0,不会漏抓。 - 输出与
fetch一致:每篇落盘为markdown/<序号>_<标题>.md,含标题、公众号、发布时间、原文链接;同样遵循config.json的write_html(默认只出 Markdown)。 - 目录命名:
<公众号名>_专辑_<album_id 末 6 位>_<时间戳>,便于和单账号抓取结果区分。 - 若链接缺少
__biz/album_id,或登录态失效(合集返回 0 篇),会给出明确报错提示先ensure-login。
典型场景:用户丢来一个"XX 系列课(共 N 篇)"的合集链接,直接 album 一把梭,不必一篇篇去找种子再翻历史。
5. 给出结果摘要
至少汇报这些信息:
- 命中的公众号名称
- 本次抓取篇数
- 成功 / 失败数量
- 输出目录
articles.json路径- 当前登录态是“复用已有缓存”还是“本轮扫码新登录”
关于"指定时间范围"
工具现在原生支持时间窗:--since / --until 在后台翻页时就会按(默认中国时区的)发布日期过滤,遇到比 --since 更老的文章会立即停,不会把过期/过时旧文拉下来。
推荐工作流:
- 先用
--dry-run --since <起始日>预览将要抓取的清单(不落盘),确认范围与数量。 - 确认无误后去掉
--dry-run正式抓取;如需续抓加--resume。 - 若目标时间段跨度很大(超过单轮
article_limit),先调大article_limit或分多轮--resume接力。
这套时间窗已按中国时区对齐,不要再让用户"把截止日往前设 1 天"来补偿 UTC 偏移。
输出物说明
默认输出结构类似:
<output_parent>/输出文章/<公众号名_时间戳>/
markdown/
html/ # 仅当开启 HTML 输出时存在(默认开启;--md-only 或 write_html:false 时不生成)
articles.json
每篇文章通常会有:
- 一份 Markdown
- 一份原始 HTML(开启 HTML 输出时)
索引文件 articles.json 适合:
- 批量分析
- 后续仿写模板生成
- 做时间筛选
- 统计抓取成功率
隐私与安全边界
必须遵守:
- 登录态只允许保存在本机项目目录
- 不要把
.playwright-profile上传到云端 - 不要把登录缓存打包发给别人
- 不要把 cookie、token、profile 内容直接展示给用户
- 除非用户明确要求,否则不要执行
clear-login
如果用户说要把机器或项目交给别人:
cd "内容生产龙虾/公众号作者文章抓取"
./scripts/run_fetcher.sh clear-login --json
并明确告诉用户已清理这两个目录:
.playwright-profilelogin_artifacts
失败处理
登录相关
- 如果
ensure-login长时间卡住,检查login-status --json - 如果二维码为空白,说明二维码文件生成异常,不能假装可扫
- 如果
status = timeout,提示用户重新发起登录
工具相关
- 如果
./scripts/.venv/bin/python不存在,优先通过./scripts/run_fetcher.sh自动补环境 - 如果
./scripts/main.py不存在,说明当前 skill 自带抓取器不完整 - 如果
fetch失败,要把错误原样转述给用户,并附上当前命令和关键路径
抓取结果相关
- 如果
downloaded = 0,不能说“已完成” - 如果
failed > 0,要明确说失败篇数和可能原因
推荐汇报格式
当状态是 waiting_scan 时,用这种结构:
当前状态:等待扫码登录
二维码图片:<qr_png_path>
二维码文本:<qr_text_path>
下一步:请扫码,扫码后我继续轮询登录状态
当抓取完成时,用这种结构:
抓取完成
公众号:<account_name>
抓取结果:成功 <downloaded> 篇,失败 <failed> 篇
输出目录:<output_dir>
索引文件:<index_file>
与其他内容生产 skill 的衔接
抓取完成后,常见下一跳是:
公众号作者仿写模板生成- 用抓下来的 Markdown 建作者风格模板
公众号标题与开头拆解- 重点拆标题、开头钩子和叙事切口
公众号文章写作- 把作者风格和情报素材拼起来正式写稿
公众号信息深挖与多源核验- 对抓到的主题继续做多源验证和补充事实
示例触发
示例 1
输入:把 Rockhazix 这个公众号最近 50 篇文章全抓下来,我后面要做仿写。
处理:触发本 skill,先确保登录,再批量抓取并返回输出目录。
示例 2
输入:我给你一篇公众号链接,你去把这个作者最近的文章都下载成 Markdown。
处理:触发本 skill,用 fetch 命令执行一条龙抓取。
示例 3
输入:先删掉登录状态,我重新扫码,你抓完后告诉我文章都存到哪了。
处理:先 clear-login,再 ensure-login,登录成功后执行 fetch。