用途
soia-pkm-clip-wechat-account 是 clip 家族的公众号批量成员,面向「把我自己公众号的历史文章一次性拉进 vault」的批量场景。它只用于归档你自己管理的公众号,不是通用的公众号爬虫;单篇、贴 URL 归档的场景由 soia-pkm-clip-wechat-article 负责。
主要能力
技能支持三条抓取路线,并把结果统一落地到 Obsidian vault:
- 路 A · 官方 API:调用 /cgi-bin/token 获取 access_token,再用 /cgi-bin/freepublish/batchget 获取成功发布列表、/cgi-bin/material/batchget_material 获取永久图文素材。需要已认证服务号/订阅号与 AppID/AppSecret,且长期有效并配置 IP 白名单。
- 路 C · 公众号后台接口:默认走 appmsgpublish 读当前登录账号的发表记录;传入 --name 或 --fakeid 时改走 searchbiz + appmsg?action=list_ex 读取指定账号。凭据为 token 与完整 Cookie,社区报告通常几小时过期。
- 路 B · 登录态 Cookie:调用 mp profile_ext 的 action=getmsg 接口翻页拉取历史文章,需 __biz/key/pass_ticket/appmsg_token 与 Cookie,票据有效期从几小时到几天。
三条路线落地时按 url 递归查找是否已归档,已存在则默认跳过,--force 才覆盖,交替运行不会重复落地同一篇。
使用方式
安装命令:
npx skills add soia-team/soia-open-skills -g -a '*' -s soia-pkm-clip-wechat-account -y
配置约定路径为 ~/.config/soia-skills/soia-open-skills/soia-pkm/soia-pkm-clip-wechat-account/config.yml,可用环境变量 SOIA_PKM_CLIP_WECHAT_ACCOUNT_CONFIG_FILE 覆盖(兼容别名 SOIA_PKM_CLIP_GZH_CONFIG_FILE、SOIA_PKM_CLIP_GZH_ENV_FILE)。秘钥、cookie、token 只能放进私有 config.yml、进程环境或 provider 登录态,不能写进仓库、vault 正文或日志。
三条路线的调用示例:
python3 scripts/fetch_api.py [--out <目录>] [--limit N] [--dry-run] [--vault <path>] [--account-name <显示名>] [--force] [--page-size 20]
默认读自己当前登录账号
python3 scripts/fetch_mp.py [--out <目录>] [--limit N] [--dry-run] [--vault <path>] [--account-name <显示名>] [--force] [--sleep 3] [--page-size 20]
读取指定账号
python3 scripts/fetch_mp.py --name <公众号名> [--out <目录>] [--limit N] [--dry-run] [--vault <path>] [--account-name <显示名>] [--force] [--sleep 3] [--page-size 5]
python3 scripts/fetch_cookie.py --biz <__biz> [--out <目录>] [--limit N] [--dry-run] [--vault <path>] [--account-name <显示名>] [--force] [--sleep 1.5]
执行前建议先用 --dry-run --limit 3 之类的小样本探路,向客户报告预计处理的公众号、篇数量级与时间范围,客户确认范围后再放开全量抓取;只有客户当前这句话明确说「直接抓/不用确认」才可跳过确认,并在回执里说明沿用的范围假设。
路 B / 路 C 走非官方接口,首次使用需展示声明并取得客户显式同意,同意后把 {accepted: true, acceptedAt: <ISO 时间戳>, disclaimerVersion: "v1"} 写入私有配置目录下的 consent.json。路 A 不受此 consent 约束。
落地规范
默认输出目录为 Inbox/gzh-articles/<年>/,可用 --out 或 env.OBSIDIAN_GZH_OUT 覆盖。文件名格式为 <出版日期>-公众号-<账号显示名>-<标题>.md,同名冲突按 url 特征加短后缀。frontmatter 包含 tags:[公众号原创, 待归位]、source: 公众号自有、url、title、author、published_at、captured_at、route: api|cookie|mp-backend、content_complete、topics: []。正文由 HTML 经 stdlib html.parser 转 Markdown,不保证 100% 还原排版;content_complete: false 表示正文抓取失败或为空,需要人工核对原文链接。列表接口不返回 author 字段时,落地用 --account-name / WECHAT_ACCOUNT_NAME 兜底,不保证等于真实署名作者。
适用场景
- 路 A 适合抽查、核对、增量同步已发布内容;但由于 freepublish/batchget 只返回通过草稿箱「发布」发出的文章,且自 2025-07 起个人主体、未认证企业主体等账号的「发布能力」接口权限被回收,多数个人订阅号大概率跑不通,需要已认证服务号/订阅号。它不适合当作全量备份。
- 路 C 是读自己号全部历史(含手动群发老文)的推荐路线,凭据只需抓一对 token/Cookie,比路 B 配对三个票据更不易出错;默认路径读当前登录账号,不存在认错号的问题。
- 路 B 作为路 C 失效时的备选。
限制
- 路 B / 路 C 为非官方接口,无官方文档背书,存在 ToS 风险,随时可能被调整,仅限归档自己管理的账号。
- token/Cookie 会过期,无刷新机制;常见错误码包括 200003 invalid session(需重新登录抓包替换)、200013 freq control(触发限流)、200040 invalid csrf token(token 与 Cookie 疑似非同一会话)。
- 存在限流风险:fetch_mp.py 默认每页/每篇间隔 --sleep 3 秒,fetch_cookie.py 默认 1.5 秒,社区报告即使 5 秒/页的节流,抓到近千篇量级仍可能触发 freq control,建议配合 --limit 分批跑。
- 归档落到 vault 的收件箱层,是中转区而非最终位置;archive 后可由 AI 逐篇补摘要、回填 topics,后续交给 organize 批量归位。