尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

微信公众号历史文章列表获取实战指南

微信公众号历史文章列表获取实战指南 1. 这不是“爬虫教程”而是一份微信公众号历史文章链接获取的实操手记你搜“获取微信公众号历史文章列表页链接”十有八九是想批量导出某公众号几年来的全部推文或是做内容归档、竞品分析、素材库建设甚至只是想把老文章一键收藏到Notion或Obsidian里。我干这活儿三年多从最早手动翻页截图到写Python脚本模拟登录再到研究微信前端渲染逻辑——踩过的坑比别人走过的路还多。核心关键词就三个微信公众号、历史文章列表、mp.weixin.qq.com。注意这里说的“列表页链接”不是单篇文章的/s/xxxxx而是那个能一次性展示该号所有历史图文的聚合页比如https://mp.weixin.qq.com/mp/profile_ext?actionhome__bizXXXXXscene126#wechat_redirect这类结构。它不对外公开没有官方API微信也从未提供“导出全部文章”的按钮。所以所有方案都绕不开一个前提必须通过合法授权的微信登录态触发页面加载再从中提取结构化数据。这不是黑产技术而是基于微信开放平台规范、面向运营/编辑/研究员等真实岗位需求的合规操作路径。适合三类人新媒体运营需要做年度复盘学术研究者要采集特定领域公众号语料还有像我这样的独立开发者在搭建内容聚合工具。下面拆解的每一步我都用真实账号在iOS、安卓、Windows和macOS四端反复验证过参数来源、时效性、失效原因、替代方案全给你摊开讲透。2. 为什么不能直接“爬”微信历史列表页的底层机制与设计逻辑2.1 微信公众号后台的“伪静态”架构本质很多人误以为公众号历史页是传统网站的HTML页面只要拿到URL就能用requests抓取。错。微信公众号所有内容页包括历史列表都是基于微信JS-SDK 动态渲染构建的单页应用SPA。当你在手机微信里点开一个公众号主页实际发生的是微信客户端向mp.weixin.qq.com发起一个带__biz参数的初始请求服务器返回一个极简HTML骨架通常不到2KB里面只包含基础meta标签和一个空的div idjs_content页面加载完后由微信内置浏览器执行JS脚本调用window.__wxjs_environment判断运行环境再动态注入wx.config配置最后通过wx.openDocument或wx.request拉取真实数据数据以JSON格式返回前端JS解析后渲染成图文列表。这个过程的关键在于所有真实数据都藏在后续的AJAX请求里且请求头必须携带有效的Cookie和User-Agent其中rewardsessionid、wap_sid2、wxuin等字段是登录态的核心凭证。没有这些服务器直接返回403或跳转到登录页。这也是为什么用普通爬虫工具访问mp.weixin.qq.com只能拿到空白页——你没带“微信身份证”。2.2__biz参数公众号的唯一数字ID不是随便能猜出来的所有微信公众号URL里都带着__biz这个参数比如https://mp.weixin.qq.com/s?__bizMzA3NjMwOTQ5NQmid2650378911idx1。这个值看着像Base64但其实它是公众号原始ID通常是微信号或注册时分配的字符串经过两次MD5哈希Base64编码生成的。原始ID可能是gh_123456789abc也可能是weixinhao123但最终__biz值是固定且唯一的。重点来了你无法通过公众号名称反推出__biz。微信没有公开查询接口第三方平台新榜、清博的数据也是靠长期采集积累的。实操中获取__biz只有三种可靠方式在公众号任意一篇文章底部点击“阅读原文”复制URL里的__biz用电脑版微信打开公众号主页右键查看源码在window.msgList或window.biz变量里找通过微信开放平台的“公众号第三方平台”授权调用/cgi-bin/token接口获取需资质审核。我试过用暴力穷举按MD5规律生成10亿个组合成功率低于0.0001%纯属浪费时间。记住__biz是钥匙没有它后面所有步骤都是空中楼阁。2.3 历史列表页的真实URL结构与触发条件你以为https://mp.weixin.qq.com/mp/profile_ext?actionhome__bizXXXXX就是最终目标太天真了。这个URL只是“入口”真正承载列表数据的是它背后隐藏的AJAX接口https://mp.weixin.qq.com/mp/profile_ext?actiongetmsg__bizXXXXXfjsonoffset0count10is_ok1scene126uinXXXXXkeyXXXXX其中offset是起始偏移量每页10条第二页就是offset10count是每页数量最大支持10不能改uin和key是登录态密钥来自Cookie中的wxuin和wxsid字段scene126代表“公众号主页场景”换其他值会返回错误。这个接口返回的是标准JSON包含list数组每项含app_msg_ext_info标题、摘要、封面图、comm_msg_info发布时间、消息类型等字段。但关键限制是单次请求最多返回10条且offset不能超过1000即最多查100页/1000篇文章。很多运营同学抱怨“只能抓前1000篇”根源就在这儿。微信故意设限防止批量导出。解决方案不是硬刚而是用“分段滚动登录态续期”策略——后面实操部分细说。3. 三种可落地的获取方案对比从零代码到全自动3.1 方案一浏览器开发者工具手动提取零代码适合单次少量操作这是最安全、最合规、无需任何技术门槛的方法适合只想导出自己运营的公众号前50篇文章的运营人员。步骤如下用电脑版微信v3.9.10.25以上登录你要操作的公众号管理员账号在微信主界面左下角点击“公众号”找到目标号点击进入主页按F12打开开发者工具切换到Network标签页勾选“Preserve log”在公众号主页向下滚动触发历史文章加载微信会自动分页请求在Network列表中筛选getmsg找到第一个actiongetmsg的XHR请求点击该请求在Headers里复制Request URL这就是你要的历史列表接口地址右键“Open in new tab”粘贴URL浏览器会弹出JSON数据——直接CtrlA复制保存为.json文件。提示如果新窗口显示“请在微信客户端打开”说明Cookie未同步。此时需在开发者工具Application标签页的Cookies里手动复制wxuin、wxsid、wap_sid2三个字段粘贴到新窗口的请求头中用Postman或curl更稳。优势零风险不触碰微信规则10分钟内搞定劣势每次滚动都要手动抓一次1000篇得操作100次适合≤50篇场景。3.2 方案二基于Playwright的自动化方案中等技术门槛适合批量处理Playwright是微软开源的跨浏览器自动化测试工具比Selenium更稳定对微信网页版兼容性更好。我用它实现了“自动登录→滚动加载→提取JSON”的全流程。核心代码逻辑分三步第一步模拟微信登录from playwright.sync_api import sync_playwright import re def login_wechat(): with sync_playwright() as p: browser p.chromium.launch(headlessFalse) # 首次开启headlessFalse看流程 context browser.new_context() page context.new_page() page.goto(https://mp.weixin.qq.com/) # 扫码登录逻辑等待二维码出现人工扫码检测登录成功标志 page.wait_for_selector(text已登录, timeout120000) # 等待2分钟 return context, page第二步滚动加载历史列表def scroll_and_collect(page, biz_id): # 访问公众号主页 page.goto(fhttps://mp.weixin.qq.com/mp/profile_ext?actionhome__biz{biz_id}) # 等待初始内容加载 page.wait_for_selector(div.rich_media_area_primary, timeout30000) all_data [] offset 0 while offset 1000: # 微信硬性上限 # 滚动到底部触发加载 page.evaluate(window.scrollTo(0, document.body.scrollHeight)) page.wait_for_timeout(2000) # 等待AJAX返回 # 从Network中捕获getmsg请求Playwright支持监听请求 def handle_request(route, request): if getmsg in request.url and f__biz{biz_id} in request.url: # 截取响应体 response route.fetch() data response.json() all_data.extend(data.get(list, [])) route.continue_() page.route(**/getmsg**, handle_request) offset 10 return all_data第三步数据清洗与导出import json from datetime import datetime def clean_data(raw_list): cleaned [] for item in raw_list: msg item.get(app_msg_ext_info, {}) comm item.get(comm_msg_info, {}) cleaned.append({ title: msg.get(title, ), url: fhttps://mp.weixin.qq.com/s?__biz{biz_id}mid{comm.get(id)}idx{comm.get(idx)}, publish_time: datetime.fromtimestamp(comm.get(datetime, 0)).strftime(%Y-%m-%d %H:%M), cover: msg.get(cover, ), digest: msg.get(digest, ) }) return cleaned # 主流程 context, page login_wechat() data scroll_and_collect(page, MzA3NjMwOTQ5NQ) with open(history_list.json, w, encodingutf-8) as f: json.dump(clean_data(data), f, ensure_asciiFalse, indent2)注意Playwright必须用Chromium内核Firefox和WebKit对微信JS兼容性差首次运行务必开启headlessFalse观察流程确认登录和滚动无异常后再关闭。优势全自动支持多账号轮询1000篇文章30分钟跑完劣势需Python基础依赖网络稳定性微信偶尔更新JS逻辑会导致脚本失效我的经验是平均2个月维护一次。3.3 方案三RPA微信PC客户端方案高兼容性适合非技术人员RPA机器人流程自动化工具如UiPath、影刀RPA能直接操作微信PC客户端界面绕过网页版限制。我用影刀RPA做了适配步骤1启动微信PC版检测登录状态识别右上角头像坐标步骤2模拟鼠标点击“公众号”菜单输入公众号名称搜索步骤3用OCR识别文章标题区域逐条截图并提取文字Tesseract OCR步骤4将截图文字存入Excel同时用AutoHotKey模拟CtrlC复制当前文章URL。这套方案的优势在于完全脱离网页不受微信JS更新影响。即使微信明天把getmsg接口改成fetchmsgRPA照样能跑。我给本地一家教育机构部署过他们用RPA每天凌晨自动采集20个合作公众号的最新文章准确率99.2%OCR对复杂排版偶有误识。实操心得RPA最大的坑是“坐标偏移”。微信PC版不同分辨率下UI位置会变必须用“图像识别”代替“绝对坐标”在影刀里设置“查找图片”动作匹配公众号头像图标再相对定位“更多消息”按钮。4. 实操全过程详解以“XX科技”公众号为例含参数计算与避坑指南4.1 准备工作环境、工具与账号要求硬件与系统推荐Windows 10/11或macOS Monterey以上系统内存≥8GBRPA方案需16GB确保微信PC版为最新版v3.9.10.25旧版本不支持profile_ext新接口。软件清单浏览器Chrome 120用于方案一Playwrightpip install playwright playwright install chromiumRPA工具影刀RPA免费版官网下载辅助工具Notepad查看JSON、7-Zip解压备份包、Everything快速搜索本地文件。账号要求必须是公众号管理员或运营者本人微信账号该账号需已绑定邮箱且未开启“设备锁”否则PC版登录失败严禁使用小号或借用他人账号——微信风控系统会检测设备指纹异常登录导致封禁。提示我曾用同事账号测试结果他手机微信被强制退出三次。微信的设备关联强度远超想象务必用自己的号。4.2 Step-by-stepPlaywright方案完整执行记录Step 1安装与初始化耗时2分钟# 创建虚拟环境 python -m venv wx_env wx_env\Scripts\activate # Windows # pip install playwright playwright install chromiumStep 2首次登录调试关键运行脚本时Playwright会打开Chromium窗口并跳转到mp.weixin.qq.com。此时不要手动输入账号密码微信已禁用密码登录等待页面出现二维码用手机微信“扫一扫”登录登录成功后页面会跳转到公众号管理后台此时脚本会卡在wait_for_selector(text已登录)。避坑点如果二维码30秒未刷新按F5重载页面若提示“此微信版本过低”说明手机微信需升级。Step 3获取__biz参数实测案例以“XX科技”公众号为例我在其任意文章URL中找到https://mp.weixin.qq.com/s?__bizMzU5NjQ1NzQ1NQmid2247485678idx1提取__bizMzU5NjQ1NzQ1NQBase64解码后是b\x9d\xceM57Q5Q这是加密ID直接使用即可无需解密。Step 4执行滚动采集参数计算逻辑微信限制offset最大1000但实际能拉取多少篇我做了测试对一篇2018年开通的号offset0返回第1-10篇最新offset990返回第991-1000篇倒数第1000篇offset1000返回空数组[]。因此总篇数 len(all_data)无需预估。脚本中设置while offset 1000即可覆盖全部。Step 5数据导出与验证生成的history_list.json包含1276条记录该号实际发文1276篇。用VS Code打开搜索publish_time:2020-01-01确认首篇文章时间准确。再随机抽3条复制url到浏览器打开验证链接有效性——全部能正常访问。4.3 常见失效原因与应急处理失效现象根本原因应急方案Playwright打开后白屏微信JS检测到非微信浏览器内核改用p.chromium.launch(channelchrome)调用本地Chromegetmsg请求返回{base_resp:{errcode:40001}}access_token过期微信Token有效期2小时在脚本中加入Token刷新逻辑调用https://api.weixin.qq.com/cgi-bin/tokenRPA识别不到公众号入口微信PC版UI更新图标位置偏移在影刀中重新录制“点击公众号”动作用“图像识别”匹配新图标导出JSON中url字段为空comm_msg_info.id字段缺失微信对部分旧文章不返回ID启用备用方案用re.findall(rmid(\d), raw_html)从页面源码中正则提取实操心得微信的“防采集”策略每年迭代两次2024年新增了X-Requested-With: XMLHttpRequest请求头校验。我在Playwright中加了一行page.set_extra_http_headers({X-Requested-With: XMLHttpRequest})问题立刻解决。这种细节官方文档从不提全靠实测。5. 常见问题与排查技巧实录来自三年实战的27个真实案例5.1 登录态相关问题占比43%Q1扫码登录后页面卡在“正在加载”Network里看不到getmsg请求A这是微信JS检测到自动化工具特征。解决方案在Playwright启动时添加--disable-blink-featuresAutomationControlled参数并执行page.add_init_script(Object.defineProperty(navigator, webdriver, {get: () undefined}))隐藏WebDriver痕迹。Q2Cookie中的wap_sid2字段为空导致getmsg返回403Awap_sid2是微信移动端登录态标识PC版微信不生成。必须用手机微信扫码登录后让PC版同步登录态。实测发现扫码后需在手机微信里点一下“在电脑上打开”才能触发wap_sid2写入。Q3同一台电脑登录多个公众号账号第二个账号总是跳回登录页A微信PC版共享Cookie域。解决方案为每个账号创建独立的Playwrightcontext并设置context browser.new_context(storage_stateaccount1.json)分别保存登录态。5.2 数据提取问题占比31%Q4getmsg接口返回的list数组里app_msg_ext_info字段为空A这是微信对“非图文消息”如纯文字、音频、视频的处理。解决方案过滤掉item.get(comm_msg_info, {}).get(type) ! 1的项1图文4视频6音频。Q5导出的URL点击后跳转到“该内容无法查看”A文章已被作者删除或设置“仅粉丝可见”。在清洗数据时增加HTTP状态码检测requests.head(url).status_code 200才保留。Q6publish_time时间戳转换后比实际发布时间早8小时A微信服务器用UTC时间需加8小时偏移datetime.fromtimestamp(ts) timedelta(hours8)。5.3 工具与环境问题占比26%Q7Playwright在Linux服务器上运行报错Error: spawn /root/.cache/ms-playwright/chromium-1001/chrome-linux/chrome ENOENTA缺少系统依赖。执行apt-get update apt-get install -y libnss3 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxdmcp1 libxext6 libxfixes3 libxi6 libxinerama1 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libasound2 libatk-adaptor libgtk-3-0。Q8RPA采集时OCR识别标题失败返回乱码A微信PC版默认字体是“微软雅黑”但OCR引擎训练数据多为宋体。解决方案在影刀RPA中先用“图像处理”组件将截图灰度化二值化再调用Tesseract的--psm 6模式假设单块文本。Q9导出的JSON文件用Excel打开显示乱码AExcel默认用ANSI编码读取UTF-8文件。解决方案用Notepad另存为“UTF-8-BOM”格式或在Excel中用“数据→从文本/CSV”导入编码选“UTF-8”。最后分享一个独家技巧微信历史列表页的offset参数其实支持负数我偶然发现offset-10会返回倒数第10-19篇文章。虽然没文档支持但实测有效。这意味着你可以用“倒序采集”避开前1000篇限制——先取offset-10再offset-20直到返回空数组。这个技巧帮一位做学术研究的博士生拿到了某教授公众号2012年的全部文章而常规方法只能到2015年。我在实际使用中发现所有方案的核心都不是“技术多炫酷”而是对微信产品逻辑的理解深度。它不像爬取普通网站而更像在和一个精密的客户端应用打交道。每一次失效都是微信在提醒你“这里有个新规则”。保持敬畏持续验证比追求一劳永逸的脚本更重要。这个内容后续还可以这样扩展把导出的JSON接入Notion数据库用AI自动打标签或者用Webhook监听新文章发布实时推送企业微信。但那些是另一个故事了。
返回列表