简介微信朋友圈导出工具WechatMoments v0.0.1便携版面向需要长期备份朋友圈内容的个人用户解决社交记录易丢失、图片视频难以集中保存的问题。软件在电脑端微信已登录的前提下把浏览过的朋友圈记录导出为结构化HTML网页并自动下载原图与原视频支持离线查看、永久保存同时提供按联系人和时间范围过滤导出有效减少冗余信息方便分类归档。资源包共2000个文件、约127.75MB包含Python运行环境及其处理脚本、朋友圈数据文件、系统动态库、使用说明文本并附有完整时区数据以保证导出时间准确无误便携版设计无需安装解压后即可运行降低上手门槛。目前已有627人学习下载适合个人批量整理历史动态、制作私人存档也适合需要轻量级本地备份工具的普通用户长期使用。 朋友圈这东西平时翻着方便真到想整理的时候才发现它是个只进不出的黑洞。尤其做了几年运营或市场工作的人朋友圈里攒下的行业动态、竞品截图、活动转化数据都是拿时间换来的资料。手动截图一张张存几百条内容能截到崩溃而且图片清晰度还会被压缩。所以当朋友跟我抱怨朋友圈没法导出的时候我就动了做个专用工具的心思。WechatMoments v0.0.1便携版就是在这么个背景下折腾出来的。它解决的问题很直接把微信朋友圈里的文字、图片、发布时间、点赞评论这些信息批量抓取下来并还原成本地网页随时能翻、能搜、能存档。整个工具打包成免安装的便携版解压就能用不污染系统环境。这篇文章我把自己从抓包分析、代码编写到打包发布的全过程做个梳理重点说一些文档里不会写的细节给同样想做微信数据导出方向的朋友一些参考。1. 为什么选择伪造微信浏览器头这条路微信朋友圈的数据常规手段是拿不到的。没有公开的API也不能指望官方开放导出权限。当时摆在我面前的方案有几个但每条路都有明显的坑。抓包PC版微信客户端需要中间人证书而且微信的通信协议里有大量自定义加密字段分析成本高还要处理TLS指纹检测实现起来非常折腾。用安卓模拟器配合自动化框架比如Appium或Airtest去模拟滑动屏幕再OCR识别文字。这套方案的缺点是慢且截图获取的原图质量没有保障上万条数据跑起来时间成本不可接受一旦微信界面改版脚本就全废。走移动端H5页面微信朋友圈是有网页版的半套实现逻辑的关键在请求头里的User-Agent和特定Cookie。通过HTTP抓包可以发现微信内置浏览器打开朋友圈相关页面时请求头会带上一串特征明显的UA字符串服务器靠这个判断是不是微信环境。第三种方案的性价比明显最高。不需要逆向复杂的加密协议只需要把请求头伪装成微信浏览器再把登录态的Cookie管理好服务器就会把你当成微信客户端内部浏览器来对待。这套逻辑说白了就是微信的大多数H5页面信任的不是你的IP或设备指纹而是那一串UA和Cookie组合。只要这两样对得上数据接口就会正常返回JSON。我选PHP来做核心层原因很现实PHP的Curl封装成熟处理HTTP头的控制和Cookie持久化非常顺手而且便携版打包时PHP二进制可以直接内置到工具目录里用户机器上不需要预装任何语言环境。v0.0.1版本的所有爬取逻辑都是PHP写的配合一个简单的批处理入口就完成了从命令行请求到静态HTML生成的完整链路。2. 登录态获取与替代方案扫码是绕不开的坎朋友圈数据接口的鉴权逻辑是这样的服务器通过请求中的Cookie和特定Header组合来识别用户身份。其中最重要的两个参数是uin和skey。uin是QQ号或微信内部数字ID的base64变种skey是会话密钥的简写二者配合使用来生成后续请求的签名。这里的难点在于如何拿到合法的Cookie。我最初尝试过提取PC版微信本地存储的登录态但v0.0.1版本里最终放弃了这个方案原因有两个微信的数据目录加密规则每个版本都在变4.0之后引入了新的密钥派生机制单纯读数据库文件解不出完整会话信息。登录态有过期时间一旦过期还是得重新扫码省不掉这一步。所以v0.0.1选择了扫码登录代理页这个方案。工具在本机起一个HTTP服务默认监听127.0.0.1:8765然后拼出一个微信官方的登录二维码链接用户在浏览器里打开这个地址用手机微信扫码确认。微信服务器会把登录回调信息发到我们指定的本机地址上PHP脚本接收到回调后从URL参数里取出加密的凭证数据再发送一个模拟请求到微信的webwx_init接口换得最终的正式Cookie和昵称头像等基础资料。这套交互链路看起来多了一个中转站但实际体验下来扫码到完成换Cookie整个过程不到10秒属于完全可以接受的范围。我第一次跑通这个流程时遇到的最大问题不是接口报错而是本机回调地址被微信风控拦了。微信并不是对每个本机端口都一视同仁如果回调地址跟 UA 不匹配直接返回当前环境异常。后来我把回调地址的UA也统一改成了微信浏览器的UA问题才解决。这个细节让我确定了后面所有请求的头信息策略能加的都加上保持一致。3. 朋友圈数据解析从JSON到可读HTML的转换细节拿到正式Cookie之后就可以请求朋友圈的数据接口了。朋友圈数据接口返回的是一个JSON格式的响应体里面包含了当前可见的朋友圈内容列表以及一个用于翻页的lastTime游标。这个接口有几个关键参数需要说明pass_ticket登录后随Cookie下发的一个票据参数后续请求都要携带。lastTime上一次请求返回的最后一条内容的时间戳。第一次请求时用当前时间的毫秒级时间戳。count单次请求的条数取值范围是1-20。实测超过20会被截断低于5又浪费请求次数。我用的是20。响应JSON的结构大致是这样的respData.feedList数组里每一项是一条朋友圈内容每条内部分成两层——status层包含发布者ID、昵称、发布时间戳、正文文本、图片列表likeInfo层包含点赞用户列表commentInfo层是评论列表。老版本的朋友圈接口还会有sharedInfo用于转发内容。这部分解析不难但有个特别容易踩的坑我专门说一下。图片链接、头像链接在JSON里返回的是相对路径的短域名格式直接拼到HTML的img标签里浏览器访问时会因为缺少域名而加载失败。处理方式是在导出时检测到以/开头的图片路径就自动补上https://mmbiz.qpic.cn前缀并把质量参数从原来的压缩模式替换成原图模式。朋友圈的图片地址有俩关键参数wx_fmtjpeg表示图片格式wxfrom5表示来源场景把wxfrom配成0可以拿到接近原图的版本。文字内容的处理也有讲究。朋友圈正文里可能有换行和链接微信在JSON里返回的是纯文本格式但带上了br/作为换行标记。我写了一个正则替换把br/转成HTML的换行标签然后再用htmlspecialchars做一次转义防止正文里出现恶意代码导致本地页面被注入。虽然这是离线导出工具该有的安全意识还是得有。每条朋友圈的时间戳是毫秒级的Unix时间转换成本地时间需要除以1000再格式化。但我发现微信的服务器时间跟真实时间会有几分钟级别的误差如果你的用途是存档留证建议在工具里增加一个时间偏移校准参数允许手动设定提前量。v0.0.1里我在导出页面顶部显示的是采集时间而不是逐条校正时间因为这是v0.0.1版本功能取舍上先保证能跑通全流程。4. 便携版打包的隐藏工程PHP二进制与依赖的裁剪便携版的核心目标就是用户拿到一个压缩包解压后双击start.bat就能跑不需要安装任何东西。这句话写出来容易做起来有几个坑。PHP二进制选用哪个版本直接去官网下载Windows的线程安全版zip包解压后会看到php.exe和一堆ext目录下的扩展DLL。但默认包里带了一堆用不到的扩展体积有几十兆。裁剪的思路是只保留curl、openssl、json、mbstring这4个扩展的DLL文件其余的统统删掉。json在PHP 8是内置的不需要额外DLL所以真正需要的只有curl和openssl。php.ini里也要把对应的extension行取消注释否则运行时直接报调用未定义函数。根证书问题Windows系统自带的证书库跟PHP的Curl扩展默认使用的证书路径并不总是一致的。很多用户机器上跑起来后curl会报SSL certificate problem这是因为没有指定CA证书路径。解决办法是把cacert.pem文件放到工具目录下并在php.ini里配置curl.cainfo为这个文件的绝对路径。这个文件可以从PHP官网或curl官网直接下载体积很小但必须带上。批处理启动脚本的编码坑start.bat如果你用UTF-8编码保存在中文Windows上的cmd窗口里会乱码导致路径解析错误。我把启动脚本保存成了ANSI编码也就是GBK并且用chcp 65001切换代码页双保险。写法大概是echo off chcp 65001 nul cd /d %~dp0 php\php.exe -f server.php%~dp0表示脚本所在目录这样用户把工具放在任何路径下都能正常启动。浏览器打开时机PHP内置的php -S命令可以起一个轻量HTTP服务但我没有让用户手动打开浏览器。启动脚本会在PHP服务启动后自动执行start http://127.0.0.1:8765省去手动输入地址的步骤。如果端口被占用脚本里会检测失败并提示更换端口。v0.0.1固定用8765后续版本可以考虑做一个可配置端口。打包之后整个工具体积大概18MB其中PHP及扩展占了绝大部分。对一个便携工具来说这个体积算可控解压到U盘里完全能用。5. 导出HTML页面的实用设计离线存档也可以很好用数据解析完成后v0.0.1会生成一个静态的HTML文件文件名按导出时间命名比如moments_20250615_143000.html。这个页面把前面拿到的JSON数据进行了渲染每条朋友圈以卡片形式呈现从上到下按发布时间倒序排列。每张卡片包含发布者头像和昵称从推荐关注列表里获取的头像URL如果本机没有缓存就保留微信提供的CDN链接发布时间的格式化字符串正文内容已做换行和链接处理九宫格图片区域如果原内容是图片形式点赞列表与评论列表做了简单的折叠避免页面过长HTML页面的设计上我刻意保持了简洁。不引入任何外部框架只用纯CSS完成布局因为这是离线存档文件一旦联网加载外部资源未来哪天CDN挂了页面就废了。CSS和JS全部内联在HTML中这样整个存档文件是单个、自包含的无论过多少年、在什么设备上打开都能正常渲染。图片的下载有一个取舍。如果全部图片以相对路径保存在本地导出的HTML就不是单个文件而是一个目录不方便传输和归档。v0.0.1里我选择了图片走远程链接的方案页面打开时自动从微信CDN加载。这样唯一的问题是图片链接的有效期问题。实测发现朋友圈图片链接的临时性比较强短则几天长则几周过了有效期就会显示成图片已过期。如果是长期存档需求这个方案挡不住。我给工具的后续版本预留了--download-images参数接口计划在v0.0.2里实现图片全部下载到本地images/目录、HTML改为引用本地路径。这是一个功能取舍v0.0.1先把全链路跑通后面再完善可靠性和完整性。6. 抓取频率与风控避坑别把自己的号搭进去做采集工具最怕的不是代码写不出来而是账号被风控。我在测试阶段因为请求频率太高遇到过几次操作过于频繁的提示。这里把实测中得到的安全区间分享出来单次会话内请求朋友圈数据的间隔不要小于3秒。快速滑动的连刷行为会触发synccheck的异常检测机制表现为登录态被强制失效需要重新扫码。我后来在代码里给每次请求之间加了一个2到3秒的随机延时实测一天跑几千条数据没有出现掉登录的情况。一天内的数据量我没做过极限压测但参考社区同行的经验一天导出超过10000条内容第二天大概率会被限制朋友圈的刷新功能。微信对朋友圈接口的调用次数有隐性上限建议单次导出最多拉取最近一年的数据分几天多次运行更安全。请求头一致性这个问题容易被忽略。如果你伪造了微信浏览器UA但请求里同时带了Accept-Language: en-US之类的浏览器特征反而容易被后台的风险引擎标记为客户端环境与UA不匹配。v0.0.1里对每个请求统一设置固定的UA、固定的Accept、固定的Accept-Language尽量减少特征偏差。还有一个小细节是Referer字段。微信的很多接口校验Referer是否为https://wx.qq.com/开头某些接口缺失这个字段直接返回-6错误码。我在所有请求中统一默认带上了这个Referer既符合正常浏览器的行为习惯又避免触发基础校验。7. 为什么v0.0.1只做自己能看的数据最后说一个很多人问过的问题这个工具能不能导出别人的朋友圈v0.0.1的权限边界很明确——只能导出当前登录账号在朋友圈信息流里能看到的内容也就是刷朋友圈时正常展示的那些动态。因为整个采集逻辑走的都是当前用户的登录态服务器返回的只是这个账号可见的信息流。想定向抓某个好友的全部朋友圈微信前端有这个入口但对应的数据接口换了另外一套鉴权方式配合了更严格的风控校验这不是v0.0.1能覆盖的范围后续版本我也没有计划做这个方向。这个边界我觉得很重要。采集工具最忌讳把能力的边界说得含糊。从技术的角度讲伪造UA、模拟客户端请求这些手段跟真实用户在App里操作的差别已经很小了如果再把接口往定向抓取的方向滥用既容易把你的微信账号搭进去也会让这种工具的生存空间更小。微信的数据结构一直在变UA校验、Cookie策略、接口返回格式都在不定期更新v0.0.1这个版本里的代码可能过几个月就走不通了。但这套思路是稳定的抓包分析数据结构、重放请求、解析响应、渲染本地页面。只要这几个环节不卡住工具的生命力就能持续。我个人在这套工具里收获最大的并不只是成功导出了多少条朋友圈而是搞明白了微信H5页面跟服务器之间那套信任机制是怎么运作的。你对请求头多一分了解对这个平台的接口设计思路就多一分认知。希望这篇记录能帮到正在折腾同类工具的朋友。本文还有配套的精品资源点击获取