公众号文章批量下载与离线归档:图片防盗链怎么破

公众号文章是网页,理论上「另存为」就能存。实际做一遍就会发现两个问题:保存下来的 HTML 打开后图片全是空白,以及一篇文章存成一个文件夹,几百篇之后根本没法管理。

这篇讲清楚为什么,以及一套能长期用的归档结构。

文章 URL 里的信息

https://mp.weixin.qq.com/s?__biz=MzA5xxx==&mid=2247483xxx&idx=1&sn=abc123...
  • __biz:公众号的唯一标识,同一号的所有文章都一样;
  • mid:一次群发的批次 ID,同一次推送的多篇文章共用;
  • idx:这条推送里的第几篇(1 开始);
  • sn:文章级校验串。

知道了这个结构,去重和排序都不用看标题——直接按 __biz + mid + idx 建主键就行,改过标题的文章也不会重复入库。

正文在哪

正文容器是 #js_content,标题在 #activity-name,作者和发布时间在 #js_name 与 #publish_time 附近。抓取的时候直接定位这几个节点,比用「取 body 里的文字」稳得多,因为页面里混着大量脚本和推荐位。

图片为什么存不下来

图片域名是 mmbiz.qpic.cn,带防盗链:请求头里没有合法的 Referer 就直接返回 403 或一张占位图。所以:

  • 浏览器「另存为网页(完整)」有时能带上,有时不带,取决于时机;
  • 用脚本下载时必须显式设置 Referer: https://mp.weixin.qq.com/;
  • 公众号图片还有一种「data-src」延迟加载的写法,真实地址在 data-src 而不是 src,不处理就会存到一堆占位图。

一套能长期用的目录结构

archive/
└── 公众号名/
    ├── index.html          # 文章列表(本地生成)
    └── 2026-11-03_标题/
        ├── article.html    # 正文,图片改成本地相对路径
        ├── meta.json       # 标题/作者/时间/原文链接
        └── img/
            ├── 001.jpg
            └── 002.png

关键是把图片下载到本地后改写 HTML 里的 src,否则一旦原图被清理,本地这份还是废的。同时把原文链接记在 meta.json 里,将来要核对出处方便。

批量抓取要注意的三件事

  • 频率:公众号侧对高频访问有风控,触发后会给验证码甚至临时封 IP。并发控制在 1–2,每次请求间隔 2 秒以上,一个号一次抓完就收手。
  • 登录态:有些文章需要关注才能看全文,那就得带 cookie。cookie 会过期,别指望一次配置管一年。
  • 已删文章:被删除的文章返回的是「该内容已被发布者删除」,这时候只能靠历史快照或别人已存的副本,抓取端无能为力。

存档的意义和边界

存下来自己看、做笔记、离线检索,都没问题。但把整号内容扒下来重新发布、做成付费资料、或者搬运到自己的站上,涉及著作权,这就不是技术问题了。存档和搬运之间隔着一整个法律章节。

相关阅读