
简介这是一份面向Python初学者的微信公众号文章URL采集爬虫资源包。资源围绕微信公众平台文章链接提取这一任务提供完整可运行的Python脚本从Cookie/Token获取、浏览器自动化驱动到文章链接抓取、文章信息解析和结果读取形成一条清晰的爬虫工作流其中还包含自动获取微信参数与常用接口的说明文档以及多个测试脚本方便读者对照调试与验证。包内共30个文件主要包括13个Python源码、5个Markdown说明文档、若干功能截图与txt依赖清单压缩包整体约17.22MB目录划分清晰便于按文档逐步理解实现思路同时附带了ChromeDriver驱动可降低环境配置门槛。目前已有580人学习下载代码结构完整既可直接用于研究微信公众号数据采集也可作为爬虫进阶练习的案例。 做微信公众号爬虫的人应该都体会过那种感觉——明明公众号文章是全网公开可访问的链接但你就是没办法系统性地拿到某一公众号的历史文章列表。搜狗微信只能翻最近十页微信客户端里的号主页只给你看最近几篇网页端连个入口都不给。折腾一圈下来你会发现这个平台的封闭程度比任何一个内容站点都夸张。所以这篇文章我想从一个比较特别的切入点讲从PC微信客户端本地缓存逆向公众号文章数据。这套方案不需要登录网页端、不需要处理验证码、不依赖任何第三方平台只要你的电脑能正常打开微信PC版就能把曾经在客户端里打开过的公众号文章全部捞出来。适合个人学习、数据分析、自媒体竞品调研这类场景也适合想深入了解微信客户端本地存储机制的Python爬虫爱好者。1. 微信公众号的抓取难点到底在哪里封闭生态与接口限制微信公众号的内容分发逻辑和传统网站完全不同。传统网站有站点地图、有栏目页、有Tag聚合爬虫只要顺着入口一层一层往下钻就行。但公众号没有公开目录也不存在一个公众号主页的网页版可以让Requests直接访问。最大的问题是接口层面的封锁。微信公众平台的网页版登录需要扫码之后能拿到的接口权限也极其有限。普通订阅号的后台只能看到用户画像和文章数据没有对外开放文章列表的API。搜狗微信搜索虽然能通过关键词找到公众号文章但它做了严密的JS渲染和Cookie校验而且最多只能翻到最近十页左右一旦翻多了直接弹验证码。我试过用Selenium去模拟搜狗微信的翻页前两页还好第三页开始频繁出现滑块验证根本没法稳定跑。另外一个隐蔽的限制是链接时效性。微信公众号文章的永久链接格式是固定的https://mp.weixin.qq.com/s?__biz...mid...idx...sn...。这里的__biz参数代表公众号的唯一编号mid是消息IDidx是文章在消息里的序号。理论上只要你拿到了这三个参数就可以构造出任意一篇历史文章的直链。但问题在于你从哪去拿这个参数组合搜狗微信的搜索结果里倒是带着这些参数但如前所述翻页受限而公众号号主页的JS接口又做了签名校验非微信客户端环境很难直接调用。所以很多人的思路就转到了客户端这条路——既然微信PC版用起来不受限、能翻公众号历史文章、能打开任意文章链接那它必然在本地存了数据。我要做的就是把这些数据找出来、解开来、导出来。这条路比网页端逆向靠谱得多因为PC客户端是真正的自家环境数据是明文级别或接近明文级别存在的。2. 三条技术路线对比搜狗中转、采集平台与PC缓存方案的取舍在真正动手之前我建议你把市面上可行的方案先过一遍这样你不会在错误的路线上浪费两周时间。路线一搜狗微信搜索中转原理是请求https://weixin.sogou.com/weixin?type2query公众号名称从搜索结果里提取__biz参数再直接拼接文章列表接口。这个方案最轻量不需要客户端环境纯Requests就能跑。但实际用下来搜狗对爬虫的识别非常敏感普通User-Agent池几乎无效必须配合代理池和验证码识别服务。而且搜狗收录的文章并非全部历史文章有一定概率遗漏。我只建议用这个方案去做公众号名称到__biz的映射不要指望它做全量历史抓取。路线二第三方采集平台或开源工具比如GitHub上常见的wechat_articles_spider改一改配置就能跑。这些工具的核心思路通常是用微信PC版的HTTP代理模式把客户端的请求转发到本地代理服务器从而拿到appmsg接口的JSON数据。这个方案效率极高能拿到完整的公众号文章列表、阅读数、点赞数。但问题是它依赖于微信PC版的特定版本微信一升级就全挂。我去年用过一个版本微信升到3.9.x之后代理模式直接失效等了两个月才等到作者更新。路线三PC微信本地缓存解析本文主线这个方案完全绕开了网络请求直接读微信PC版在本地落盘的数据库文件。好处是不依赖微信版本稳定性只要数据库格式不变就能用、不需要处理反爬、数据是结构化的SQLite表拿来即用。缺点是只能拿到你在PC端打开过的公众号文章不是全量历史文章。如果你只是做竞品内容分析、某几篇文章的数据整理、或者评论内容挖掘这个方案完全够用。我把三条路线的关键差异整理成了表格对比维度搜狗微信中转代理模式采集PC本地缓存解析反爬压力高需处理验证码低但依赖微信版本无纯离线读取数据范围最近十页公众号全量历史客户端已浏览记录稳定性受搜狗策略影响微信升级易失效取决于数据库格式实现成本中高中适合场景快速拿biz参数全量历史采集个人数据整理、定向分析综合来看如果你只是想解决这个公众号最近发过什么文章、我关注的几个号都写了啥这个问题PC缓存方案是最省心的。3. 数据在哪儿PC微信客户端的缓存路径与数据库结构解析微信PC版的存储逻辑其实很直白它基于CEFChromium Embedded Framework开发公众号文章在客户端里打开时本质上就是用内置浏览器渲染了一个网页。但和普通浏览器不同的是微信会在本地把已打开过的文章缓存下来用于离线阅读和加速二次访问。先说路径。微信PC版的根目录一般在C:\Users\你的用户名\Documents\WeChat Files\下面会按wxid_xxx你的微信号对应文件夹区分用户。进去之后主要关注两个目录Msg\Multi\存放聊天记录相关的数据库公众号文章会通过聊天窗口以卡片形式出现所以这里会有对应记录。Msg\FileStorage\Msg\Multi\存放公众号文章的消息记录和部分缓存内容子目录里能直接看到db_storage之类的文件。如果你在微信里打开过某篇文章且客户端没有清理缓存那么这篇文章的链接、标题、摘要信息会落到一个核心数据库里。微信PC版的数据库全部使用SQLCipher加密文件后缀通常是.db但直接打开会提示file is not a database。这些库文件的加密密钥和微信登录态绑定每次启动客户端时动态生成。具体来说公众号文章数据主要在以下几个库里MSG.db核心消息库MSG表里有所有聊天消息包括公众号推送消息。applet.db小程序和部分网页缓存数据公众号文章链接偶尔也会在这边留痕。PublicMsg.db部分版本会单独存放公众号消息。如果你只是想拿到文章的URL和标题重点看MSG.db里的MSG表。这个表的字段很多但关键字段就几个StrTalker发送方标识公众号的__biz编码可以通过它解析出来、StrContent纯文本通常是公众号推送的摘要或文章卡片描述、CreateTime消息时间戳。而文章的真实链接一般不在MSG表里直接显示需要根据消息类型字段去关联Media表或者从StrContent里的XML结构里抽取。4. 数据库解密从内存到SQLCipher密钥的完整链路拿到了数据库文件但解不开这是很多人在这个方案里卡住的第一道坎。SQLCipher不是普通的SQLite没有密钥就是一堆乱码。要破解它得从微信PC进程的内存里把密钥抠出来。主流的做法是注入式读取。微信PC版在运行时会以一个固定的AES密钥来打开数据库这个密钥本身也存储在进程内存里。我们可以写一个DLL注入到微信进程中调用Windows的进程内存读取API在特定内存地址范围内搜索密钥模式然后回传出来。这个思路看起来复杂但社区里已经有人封装好了现成的工具。我实际用的是pywxdump这个项目。它的核心流程分三步通过pywxdump bias_addr获取微信版本对应的固定偏移地址。使用pywxdump get_info扫描微信进程自动定位并解密出所有数据库文件的密钥。使用pywxdump decrypt把加密的.db文件解密成普通SQLite文件。用起来很简单# 安装 pip install pywxdump # 获取当前微信版本号和进程信息 pywxdump get_info # 自动解密数据库 pywxdump decrypt -k 密钥 -i input_dir -o output_dir这个工具对3.9.x版本的微信支持比较好但微信更新后偏移地址会变。如果你遇到bias_addr获取失败去项目GitHub的Issues里翻一下一般半天之内就有人更新偏移库。还有一种思路是通过RPC Hook方式。wechat-dump-rs这个项目就是走这个路线它使用Rust实现通过House\精读微信客户端的内部函数调用直接在运行时把数据库内容导出来。这个方案理论上不需要关心数据库文件本身但实现门槛高而且不同Windows版本下Hook点不一样我在Win10上能跑通换Win11就报错。除非你对逆向很熟悉否则不建议从这条路入门。拿到密钥之后数据访问就变成了常规SQLite操作。解密后的MSG.db可以直接用DB Browser打开也可以用Python的sqlite3标准库读取。5. 实战代码用Python直接读取公众号文章记录我的个人工作流是这样的先用pywxdump把密钥和数据库一次性解密出来然后写一个Python脚本定期扫描新数据把公众号文章链接、标题、发布时间、正文摘录全部导成结构化表格。这样即使微信客户端不打开数据也能被我随时访问。解密后的数据读取核心代码其实很短import sqlite3 import json import re from datetime import datetime DB_PATH rD:\wechat_decrypted\MSG.db def extract_wechat_articles(): conn sqlite3.connect(DB_PATH) cursor conn.cursor() # MSG表保存了所有聊天消息公众号推送的消息类型通常是49 query SELECT StrTalker, StrContent, CreateTime FROM MSG WHERE Type 49 AND StrContent LIKE %appmsg% cursor.execute(query) articles [] for talker, content, ts in cursor.fetchall(): # StrContent是一个XML需要抽取其中的title和url title_match re.search(rtitle(.*?)/title, content) url_match re.search(rurl(.*?)/url, content) if title_match and url_match: articles.append({ biz: talker.strip(), title: title_match.group(1).strip(), url: url_match.group(1).strip(), published_at: datetime.fromtimestamp(ts).strftime(%Y-%m-%d %H:%M:%S) }) conn.close() return articles if __name__ __main__: result extract_wechat_articles() for item in result[:10]: print(item)这里有一个细节需要注意MSG表里的StrContent是XML格式的消息体appmsg节点里才包含文章真正的信息。title是文章标题url是文章链接des是摘要。公众号推送的文章一定走的是appmsg结构但聊天里别人转发的文章也是这个结构。如果你只想保留公众号主动推送的文章需要额外判断StrTalker是否是公众号标识——公众号的StrTalker一般以gh_开头或是一串很长的数字个人微信号是wxid_开头这个可以根据自己场景过滤。文章正文抓取我建议直接请求mp.weixin.qq.com的URL。微信公众号文章页面的HTML结构相对规整正文内容在div idjs_content标签内。用Requests加一个常规的浏览器UA就能拿到import requests from bs4 import BeautifulSoup def fetch_article_content(url): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } resp requests.get(url, headersheaders, timeout10) resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) content_div soup.find(div, idjs_content) if content_div: return content_div.get_text(stripTrue) return 实测下来这个方案在请求频率不高的情况下是稳定的。单篇文章抓取间隔控制在2秒以上连续抓几百篇基本不会触发风控。如果抓得太猛微信会返回环境异常的提示页这时候停个几分钟再继续就行。6. 数据落库与增量更新把缓存方案变成可持续运行的爬虫一次性把历史数据导出来并不难难的是怎么让它持续运行。公众号每天都会推送新文章如果你隔几天要重新扫一遍客户端缓存怎么判断哪些文章是新出现的我采用的方案是在本地维护一张articles表标题和URL做唯一约束每次扫描时用INSERT OR IGNORE直接写入。这样重复读取同一篇历史文章不会产生脏数据只要新文章出现在本地缓存里就会被自动捕获。import sqlite3 ARTICLE_DB rD:\wechat_data\articles.db def init_db(): conn sqlite3.connect(ARTICLE_DB) conn.execute( CREATE TABLE IF NOT EXISTS articles ( id INTEGER PRIMARY KEY AUTOINCREMENT, biz TEXT, title TEXT, url TEXT UNIQUE, published_at DATETIME, content TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ) conn.commit() return conn def save_articles(articles): conn init_db() for item in articles: conn.execute( INSERT OR IGNORE INTO articles (biz, title, url, published_at) VALUES (?, ?, ?, ?), (item[biz], item[title], item[url], item[published_at]) ) conn.commit() conn.close()这里有一个非常关键的增量更新细节微信PC端并不会保留你所有打开过的文章缓存它会在数据库膨胀到一定大小后自动清理旧数据。所以你不能指望今天能扫到的数据永远在。我一般的做法是每三天跑一次pywxdump解密然后把新数据同步到自己的数据库里这样即使微信侧的旧缓存被清了我自己这边仍然有一份完整记录。另外一个容易踩的坑是微信退出后某些数据库文件会被锁定。pywxdump在解密时需要微信进程正在运行但如果你在微信运行时就尝试读取解密后的数据库文件Windows的文件锁会导致sqlite3.OperationalError: database is locked。我的解决方法是解密完文件后立刻关闭微信然后在独立的Python进程里读取、入库。7. 稳定性优化与常见问题排查爬虫跑不起来时的完整排障思路这个方案虽然比网页爬虫稳定但也不是完全没有坑。我把自己实际踩过的问题和对应的排查过程整理出来如果你遇到类似情况可以直接对照。问题一pywxdump显示bias_addr获取失败这个报错绝大多数情况是微信版本太新工具内置的偏移地址库还没有适配。排查步骤是先看自己的微信版本号设置→关于微信再去项目的bias_addr配置里查有没有这个版本。没有的话要么用Windows的进程内存扫描工具手动定位密钥要么临时装一个旧版微信。我一般选择装旧版毕竟逆向工具链的适配速度永远追不上微信的更新速度。问题二解密出来的数据库打开是空的出现这个情况先别急着怀疑解密过程。打开微信手动在公众号里翻几篇文章让文章在客户端里实际渲染过然后再重新扫描。微信的缓存写盘是延迟的文章没有真正打开过数据库里就不会有记录。还有一个隐蔽细节公众号文章缓存不一定只存在MSG.db里有些版本会存在applet.db或FileStorage目录下的临时文件里。如果MSG.db数据量明显偏少把FileStorage目录整个翻一遍看看有没有非SQLCipher加密的JSON或HTML文件。问题三正则解析不到URL微信PC版的StrContent里的XML结构并不完全统一图文消息和视频消息的字段差别很大。纯文字消息没有url标签多图文消息每个子卡片有单独的url。我建议解析时不要只依赖一个正则而是先用XML解析器把整个appmsg节点树取下来再遍历所有url节点。这样即使字段顺序变了也不会漏。import xml.etree.ElementTree as ET def parse_msg_content(xml_str): try: root ET.fromstring(xml_str) appmsg root.find(appmsg) if appmsg is None: return None, None title appmsg.findtext(title, ).strip() url appmsg.findtext(url, ).strip() return title, url except ET.ParseError: return None, None这个函数我用了很久兼容性比正则好很多。问题四请求微信公众号文章URL出现环境异常这个提示一般是微信的反爬策略在起作用主要触发原因是请求频率过高或UA太干净。我的对策是把单次抓取间隔提高到3-5秒使用真实的浏览器UA并且每次请求时携带Referer: https://mp.weixin.qq.com/。实测这个组合能把风控触发率压到很低。如果再碰到环境异常停半小时再跑基本就恢复正常了。8. 这套方案怎么扩展从文章列表到正文、评论与数据分析如果你跑通了上述流程其实你已经有能力做很多公众号数据分析的事了。最基础的应用是公众号周报——把关注的公众号文章聚合成一张表看它们每周发布了多少篇、标题用什么关键词、正文篇幅多长。进阶一点可以做竞品内容追踪某个行业里头部账号更新了什么第一时间同步到自己的知识库。正文抓下来之后还可以进一步做NLP分析。比如用jieba提取高频词用snownlp做情感判断甚至用大语言模型对文章做摘要。我看到身边有朋友把公众号文章抓下来之后喂给本地大模型做RAG检索增强生成相当于给自己建了一个私人的公众号知识库想查什么直接问。数据和代码我就不贴了毕竟这部分已经不是爬虫的范围了。评论抓取是另一个方向。公众号文章底部的评论在页面加载时会通过一个XHR接口返回关键参数是文章URL里带的__biz和mid加上comment_id。有兴趣的可以自行用开发者工具抓包分析。但这里要提醒一句文章正文属于公开内容抓取用于个人学习研究问题不大评论涉及用户个人表达大规模采集和公开分析可能会涉及隐私边界建议仅用于个人小范围分析不要去碰用户身份信息也不要拿去商用。爬虫技术本身是中性的边界是靠使用者把握的。最后说一个我的个人习惯。我在跑这套流程时所有的数据入库操作都加了一层字段校验和去重同时定期备份解密后的数据库文件。因为微信PC版在升级时很可能会清掉旧缓存万一数据没入库就升级了之前打开过的内容就永远找不回来了。缓存文件拿到手里其实是很脆弱的及时落库才是王道。本文还有配套的精品资源点击获取