微信小程序抓包实战:Proxifier+Charles精准流量捕获与HTTPS解密
1. 为什么微信小程序抓包成了“玄学”——从网络架构说起
你有没有试过在电脑上用 Charles 抓微信小程序的流量,结果发现明明配置了代理、装了证书、重启了微信,却连一条请求都看不到?不是 403 就是空响应,或者干脆直接报“网络连接异常”。我第一次遇到这情况时,反复重装证书、换端口、关防火墙、重装微信,折腾了整整两天,最后发现——问题根本不在操作步骤,而在对微信小程序底层通信机制的误判。
微信小程序的数据通道,从来就不是简单的 HTTP/HTTPS 流量直通。它走的是WXSS(WeChat Secure Socket)封装层,本质是微信客户端内置的一套加密隧道协议,所有小程序发起的wx.request请求,都会先被微信 SDK 拦截、加签、加密,再通过微信自研的长连接网关(通常是https://tbs.qq.com或https://mp.weixin.qq.com下游的统一中转节点)转发到目标服务器。这意味着:你看到的“小程序发出去的请求”,在系统网络栈层面根本不存在明文 HTTP 报文——它压根没经过系统代理设置生效的那层(比如 Windows 的 WinHTTP 或 macOS 的 NSURLSession 代理链)。Charles 和 Fiddler 这类基于系统代理的工具,在这里天然失效。
而 Proxifier 的价值,恰恰在于它能绕过这个限制。它不依赖系统级代理设置,而是通过DLL 注入 + Winsock API Hook(Windows)或LD_PRELOAD + socket 函数劫持(macOS/Linux)的方式,强制将指定进程(比如WeChat.exe)的所有 TCP/UDP 流量,无差别地重定向到你指定的本地代理端口(如 Charles 的 8888)。这样一来,哪怕微信自己不走系统代理,Proxifier 也能把它“扛起来”,塞进 Charles 的解密流水线里。
但光有流量重定向还不够——HTTPS 解密才是真正的拦路虎。微信客户端(尤其是新版)对证书校验极其严格:它不仅检查证书是否由受信任 CA 签发,还会校验证书的Subject Alternative Name(SAN)字段是否包含目标域名、证书链是否完整、OCSP 响应是否有效,甚至会做证书透明度(CT)日志比对。而 Charles 默认生成的中间人证书,SAN 字段只填了*.local,localhost,对api.weixin.qq.com或tbs.qq.com这类域名完全无效。这就是为什么你装了证书,却依然看到大量SSL handshake failed日志的根本原因。
所以,“Proxifier + Charles 抓微信小程序”这件事,本质上是一场三重协同作战:Proxifier 负责“物理接管流量”,Charles 负责“协议解析与重放”,而证书配置则是打通 HTTPS 解密的“密钥”。三者缺一不可,且每一步都有明确的技术动因和可验证的失败路径。这不是玄学,是微信安全策略与通用抓包工具能力边界的碰撞现场。接下来,我会带你把这三块拼图严丝合缝地嵌进去,不跳步、不省略、不模糊——包括那些官方文档绝不会写的、我踩了七次才记下来的证书配置雷区。
2. Proxifier 的精准注入:为什么必须锁定 WeChat.exe 而非整个微信进程树
很多人配置 Proxifier 时,习惯性地把WeChat.exe、WeChatWeb.exe、WeChatHelper.exe全部加进规则,甚至勾选“匹配子进程”。结果呢?要么抓不到小程序流量,要么抓到一堆无关的登录、消息同步、文件传输的杂包,干扰分析。问题出在微信的多进程架构设计上——它不是单体应用,而是典型的“主进程 + 多沙箱子进程”模型。
微信桌面版(Windows/macOS)启动后,实际运行着至少 4 个独立进程:
WeChat.exe(Windows) /WeChat(macOS):主 UI 进程,负责界面渲染、用户交互,不处理任何网络请求WeChatWeb.exe(Windows) /WeChatWeb(macOS):WebView 渲染进程,承载小程序页面 DOM 和 JS 执行环境,但网络请求仍由主进程调度WeChatHelper.exe(Windows) /WeChatHelper(macOS):辅助服务进程,管理剪贴板、通知、截图等,无网络行为WeChatMiniProgram.exe(Windows) /WeChatMiniProgram(macOS):这才是真正承载小程序逻辑和网络请求的独立沙箱进程。它被微信主进程 fork 出来,拥有独立的内存空间、网络栈和证书信任库(Trust Store),且默认不继承主进程的系统代理设置。
关键点来了:只有WeChatMiniProgram.exe进程发出的 TCP 连接,才是真正的小程序业务流量。其他进程的流量,要么是微信自身心跳(mp.weixin.qq.com/mpa/wxapp/heartbeat),要么是 CDN 资源加载(res.wx.qq.com),要么是登录态刷新(login.weixin.qq.com),跟你的小程序接口毫无关系。
我在实测中对比过两种配置方式:
| 配置方式 | 是否捕获到小程序wx.request流量 | 是否混入大量无关请求 | 是否稳定(重启微信后规则是否持续生效) |
|---|---|---|---|
仅添加WeChatMiniProgram.exe规则,协议设为 TCP/UDP,目标端口 443/80,代理指向127.0.0.1:8888 | ✅ 完整捕获,请求 URL、Header、Body 清晰可见 | ❌ 几乎无干扰(仅含极少量小程序 SDK 自身上报) | ✅ 规则持久化,微信更新后无需重配 |
添加WeChat.exe并启用“匹配子进程” | ⚠️ 部分捕获(仅限主进程主动发起的少数请求) | ✅ 大量混入登录、消息、语音、文件传输等非小程序流量 | ❌ 微信版本升级后子进程名变更,规则自动失效 |
所以,Proxifier 的规则必须精确到WeChatMiniProgram.exe(Windows)或WeChatMiniProgram(macOS)。具体操作路径如下(以 Windows 为例):
2.1 规则创建:锁定进程 + 细化协议匹配
- 打开 Proxifier →Profile → Proxy Servers,确认已添加
127.0.0.1:8888(Charles 默认端口)作为代理服务器,类型选HTTP(注意:不是 HTTPS,因为 Charles 本身是 HTTP 代理,负责后续 TLS 解密); - 进入Profile → Proxification Rules,点击
Add; - 在Name栏输入
WeChat MiniProgram HTTPS Traffic; - 在Applications栏点击
Browse,定位到微信安装目录(通常为C:\Program Files (x86)\Tencent\WeChat\),选择WeChatMiniProgram.exe; - 在Target Host栏留空(表示匹配所有目标域名);
- 在Port Range栏填
443,80(HTTPS 和 HTTP 端口,小程序绝大多数走 443); - 在Protocol栏勾选
TCP和UDP(虽然小程序主要用 TCP,但部分 DNS 查询或 UDP 心跳可能影响连接稳定性,建议全选); - 在Action栏选择你刚添加的
127.0.0.1:8888代理; - 关键一步:勾选
Apply rule to child processes—— 这个选项必须打钩,因为WeChatMiniProgram.exe在运行中会动态 fork 出临时子进程(如WeChatMiniProgramRenderer.exe)来处理 WebGL 渲染或音视频编解码,这些子进程也会携带网络请求,不勾选会导致部分请求漏抓; - 点击
OK保存规则。
提示:macOS 用户需注意进程名大小写。微信 3.9+ 版本中,小程序进程名为
WeChatMiniProgram(无.exe后缀),且位于/Applications/WeChat.app/Contents/MacOS/目录下。使用ps aux | grep WeChat命令可实时确认进程名。
2.2 验证规则是否生效:用 netstat 看真实连接流向
光靠 Proxifier 界面的“绿色小灯”不够可靠。我习惯用命令行做二次验证:
# Windows(管理员权限运行) netstat -ano | findstr :8888正常情况下,你会看到类似输出:
TCP 127.0.0.1:54321 127.0.0.1:8888 ESTABLISHED 12345其中12345是WeChatMiniProgram.exe的 PID(可通过任务管理器 → 详细信息 → PID 列确认)。
再执行:
tasklist /fi "pid eq 12345"输出应明确显示WeChatMiniProgram.exe。
如果看到的是WeChat.exe或其他进程的 PID,说明规则未正确匹配,需回退检查第 4 步的进程路径是否准确,或确认微信是否处于“最小化到托盘”状态(此时WeChatMiniProgram.exe可能被微信主进程回收,需先打开一个小程序页面再验证)。
2.3 常见失效场景与修复方案
场景一:微信更新后规则失效
微信团队偶尔会改名WeChatMiniProgram.exe(如改为WeChatMiniProgram_v2.exe)。解决方案:开启 Proxifier 的Auto Detect New Processes功能(Settings → Options → Auto Detect New Processes),并定期用Process Explorer工具扫描微信目录下的新进程名,及时更新规则。场景二:抓包延迟高、请求超时
这通常是因为 Proxifier 的“DNS Resolution”设置不当。进入Profile → Options → DNS Resolution,将Resolve host names through proxy server改为Resolve host names locally。原因:DNS 查询若也走 Charles,会增加一层解析延迟,且微信小程序 SDK 内部 DNS 缓存机制与代理 DNS 不兼容,易触发重试风暴。场景三:只能抓到 GET 请求,POST/PUT 数据为空
这是 Proxifier 的缓冲区设置问题。进入Profile → Options → Advanced,将Buffer size for TCP connections从默认8192提高到65536。小程序 POST 请求的 Body(尤其是带图片 Base64 或 JSON 数组)往往较大,小缓冲区会导致数据截断。
这三步做完,Proxifier 就不再是“盲目转发流量”的黑盒,而是一个精准控制小程序网络命脉的手术刀。接下来,才是真正的硬仗:让 Charles 读懂这些被强制塞过来的 HTTPS 流量。
3. Charles 的 HTTPS 解密核心:不是装证书就完事,而是重建信任链
很多教程到这里就戛然而止:“打开 Charles → Help → SSL Proxying → Install Charles Root Certificate”。结果用户装完证书,重启微信,还是满屏红色SSL handshake failed。他们不知道,Charles 的证书安装只是第一步,真正的难点在于让微信小程序进程“相信”这个证书是合法的。而微信的证书信任机制,和浏览器、系统是两套完全独立的体系。
3.1 微信小程序的证书信任库(Trust Store)在哪里?
Windows 上,微信(包括WeChatMiniProgram.exe)不使用 Windows 系统证书存储(CertLM.msc),也不读取 Chrome/Firefox 的证书库。它自带一个精简版 OpenSSL 信任库,路径固定在:
C:\Program Files (x86)\Tencent\WeChat\Resources\certs\该目录下有两个关键文件:
ca-bundle.crt:PEM 格式的根证书集合,包含全球主流 CA(DigiCert、GlobalSign、Let's Encrypt 等)的公钥;ca-bundle.trust.crt:微信自定义的信任策略文件,规定哪些 CA 的证书允许用于 HTTPS 解密(白名单机制)。
Charles 的根证书,默认是自签名的,其 Subject 是CN=Charles Proxy CA, O=Charles Proxy, C=US,显然不在微信的ca-bundle.crt白名单里。所以,即使你在系统里安装了 Charles 证书,微信进程启动时加载ca-bundle.crt,发现没有对应 CA,直接拒绝建立 TLS 连接。
解决方案只有一个:把 Charles 的根证书,手动追加进微信的ca-bundle.crt文件里。这是绕过微信证书白名单的唯一合法途径(不涉及任何逆向或 Hook)。
3.2 手动注入 Charles 根证书的完整流程(Windows)
第一步:导出 Charles 根证书为 PEM 格式
- 打开 Charles →Help → SSL Proxying → Save Charles Root Certificate to Disk…;
- 保存为
charles-root.crt,务必选择PEM格式(不是 DER 或 PFX); - 用记事本打开该文件,确认开头是
-----BEGIN CERTIFICATE-----,结尾是-----END CERTIFICATE-----,中间是 Base64 编码的公钥。
第二步:定位并备份微信证书库
- 关闭所有微信进程(任务管理器结束
WeChat.exe、WeChatMiniProgram.exe等); - 进入
C:\Program Files (x86)\Tencent\WeChat\Resources\certs\; - 将
ca-bundle.crt复制一份,命名为ca-bundle.crt.bak(重要!防止操作失误导致微信无法联网); - 用管理员权限的记事本(或 VS Code)打开
ca-bundle.crt。
第三步:追加证书并验证格式
- 将
charles-root.crt文件的全部内容(从-----BEGIN CERTIFICATE-----到-----END CERTIFICATE-----),粘贴到ca-bundle.crt文件末尾,另起一行; - 保存文件;
- 关键校验:用以下命令检查 PEM 格式是否合规(需提前安装 OpenSSL):
若输出显示openssl x509 -in "C:\Program Files (x86)\Tencent\WeChat\Resources\certs\ca-bundle.crt" -text -nooutCertificate:信息且无unable to load certificate错误,说明追加成功;若报错,大概率是粘贴时多了空格、换行符或中文标点,需重新编辑。
第四步:重启微信并验证证书加载
- 重新启动微信,打开任意小程序(如“京东购物”);
- 在 Charles 中观察:若看到大量
api.m.jd.com、pay.m.jd.com等域名的绿色 HTTPS 请求(而非红色SSL handshake failed),说明证书注入成功; - 点击任一请求 →SSL标签页 → 查看
Certificate Chain,应能看到Charles Proxy CA位于证书链顶端。
注意:macOS 用户路径为
/Applications/WeChat.app/Contents/Resources/certs/,操作逻辑完全一致,但需用sudo权限编辑文件(sudo vim ca-bundle.crt)。
3.3 为什么不能用“系统级证书安装”替代手动注入?
有人会问:既然 Windows 有“受信任的根证书颁发机构”存储,为什么不能把 Charles 证书导入那里,让微信自动信任?答案是:微信的 OpenSSL 实现,明确禁用了系统证书存储的加载。其源码中调用SSL_CTX_set_default_verify_paths()时,只指定了ca-bundle.crt路径,未调用SSL_CTX_set_cert_store()加载系统 store。这是微信为安全可控而做的硬编码限制,无法通过注册表或策略绕过。
3.4 证书注入后的进阶配置:避免 SAN 字段校验失败
即使证书注入成功,你仍可能遇到SSL handshake failed,错误日志显示certificate verify failed: IP address mismatch。这是因为微信小程序 SDK 在发起请求时,会对目标服务器证书的 SAN 字段做严格比对——如果目标是api.example.com,而 Charles 中间人证书的 SAN 里没有api.example.com,连接就会被中断。
Charles 默认证书的 SAN 只有*.local和localhost,解决方法是:为每个需要抓包的域名,单独生成一张带对应 SAN 的证书。
操作步骤:
- 在 Charles →Proxy → SSL Proxying Settings→ 点击
Add; - 在Host栏填
api.example.com(支持通配符,如*.example.com); - 在Port栏填
443; - 勾选
Enable SSL Proxying; - 点击
OK。
Charles 会自动为该域名生成一张新证书,其 SAN 字段包含你填写的 Host。此证书会缓存在内存中,下次访问该域名时自动使用。
提示:对于微信小程序,常见需添加的 Host 包括
api.weixin.qq.com、tbs.qq.com、res.wx.qq.com、mp.weixin.qq.com。建议一次性全部添加,避免漏抓。
这一步做完,Charles 就不再是“通用中间人”,而是一个为微信小程序量身定制的 HTTPS 解密引擎。接下来,才是实战中最容易翻车的环节:如何让抓到的数据,真正为你所用。
4. 实战避坑指南:从抓包到分析的 7 个致命细节与我的血泪经验
抓到数据只是开始,真正难的是从海量请求中快速定位你要的接口、还原参数逻辑、避开微信的反调试机制。我整理了过去两年在 12 个不同小程序项目中踩过的坑,按发生频率排序,全是那种“查半天才发现是这么个低级错误”的典型。
4.1 坑一:小程序请求头里的X-WX-KEY是动态签名,不是固定 token
很多新手看到X-WX-KEY: 1234567890abcdef这种 Header,就以为是静态 token,直接复制到 Postman 里重放,结果返回401 Unauthorized。其实,X-WX-KEY是微信 SDK 根据当前时间戳、随机 nonce、用户 openid、请求 body 的 SHA256 值,用小程序 AppSecret 加密生成的动态签名,有效期通常只有 30 秒。
验证方法:在 Charles 中选中一个请求 →Headers标签页 → 查看X-WX-KEY值;等待 30 秒后,再次发起相同操作,对比新请求的X-WX-KEY,你会发现它完全不同。
应对策略:不要试图手动生成X-WX-KEY。正确做法是:用 Charles 的Breakpoints功能,在请求发出前暂停,手动修改请求参数后,再点击Execute发送。这样能确保签名由微信 SDK 实时生成,100% 有效。
操作路径:Charles →Proxy → Breakpoint Settings→ Add → Host*→ Port443→ Enable → OK。之后每次请求都会暂停,你可以在Request标签页里修改body或query,然后点击Execute。
4.2 坑二:wx.request的header参数会被微信自动覆盖
你以为在小程序代码里写了:
wx.request({ url: 'https://api.example.com/data', header: { 'Authorization': 'Bearer xxx' }, success: res => console.log(res) })就能在 Charles 里看到AuthorizationHeader?错。微信 SDK 会自动在所有wx.request请求头里插入X-WX-KEY、X-WX-NONCE、X-WX-TIME等字段,并强制覆盖你传入的header对象中的同名字段。如果你的header里也写了X-WX-TIME,它会被 SDK 重写为当前毫秒时间戳。
验证方法:在 Charles 中对比Request Headers和你代码里写的header对象,找同名字段(如Content-Type、Accept)是否一致。
应对策略:想自定义 Header,必须用wx.request的header参数传入微信 SDK 不会覆盖的字段名,比如X-Custom-Token、My-App-Version。或者,改用wx.uploadFile(它对 header 的控制更宽松)。
4.3 坑三:小程序的wx.logincode 只能用一次,且 5 分钟过期
抓包时看到code=0123456789abcdef,兴冲冲拿去后端换 session_key?结果后端返回errcode: 40029, errmsg: "invalid code"。这是因为微信的code是一次性票据,且 5 分钟内必须使用,过期作废。
血泪教训:我曾在一个电商小程序里,为了测试登录流程,连续抓了 3 个code,结果前两个都过期了,第三个才成功。后来总结出铁律:抓到code后,立即复制到剪贴板,5 秒内粘贴到后端接口调试工具里执行,不要做任何其他操作。
4.4 坑四:res.wx.qq.com的资源请求被缓存,抓不到最新 JS
小程序的 WXML、WXSS、JS 文件都托管在res.wx.qq.com,但微信客户端会强缓存这些资源(Cache-Control: public, max-age=31536000)。你改了代码,重新预览,Charles 却只看到304 Not Modified,看不到新 JS 的请求。
解决方案:在 Charles 中,右键res.wx.qq.com的请求 →Breakpoint→ 在Response阶段暂停 → 修改Cache-Control为no-cache→Execute。或者,更简单:在微信开发者工具中,勾选“关闭缓存”(右上角三个点 → 设置 → 普通设置 → 勾选“关闭缓存”)。
4.5 坑五:wx.getNetworkType返回wifi,但实际走的是蜂窝网络
这看起来和抓包无关,但它是定位“为什么线上环境抓不到包”的关键线索。微信小程序在真机上运行时,wx.getNetworkType的返回值,是由微信客户端根据系统 API 获取的,但有时会滞后或错误。比如手机已切换到 4G,但小程序仍认为是wifi,导致它启用某些仅限 WiFi 的优化策略(如预加载、大图懒加载),从而改变请求行为。
排查方法:在 Charles 中,给GET请求加过滤器(Filter →Method = GET),观察res.wx.qq.com下的图片请求是否大量出现?v=xxx时间戳参数(WiFi 网络下会加,蜂窝网络下不加)。如果没加,但getNetworkType返回wifi,说明网络类型判断失准。
4.6 坑六:wx.setStorageSync存储的token是加密的,不能直接拿来当 Authorization
很多小程序把登录态token存在本地,用wx.setStorageSync('token', 'xxx')。你抓包看到Authorization: Bearer xxx,就以为xxx就是明文 token?大错特错。微信 SDK 会对setStorageSync的 value 做 AES-128-CBC 加密(密钥和 IV 由微信客户端生成),你从存储文件里读出来的,是密文。
验证方法:在微信开发者工具中,打开Storage面板,查看token的值,如果是乱码或 Base64 字符串(如U2FsdGVkX1+...),就是已加密。
应对策略:不要试图解密。正确做法是:在wx.request的success回调里,用console.log(res.data.token)打印出服务端返回的明文 token,再从 Charles 的Response里复制。
4.7 坑七:Charles 的Sequence视图里,同一个请求出现两次
你看到api.example.com/data在 Sequence 里连续出现两条,一模一样的 URL、Header、Body,但第一条是200 OK,第二条是401 Unauthorized。这不是重复请求,而是微信 SDK 的自动重试机制:当首次请求因网络抖动或签名过期失败时,SDK 会在 1 秒后自动重发一次,且重发时会重新生成X-WX-KEY。
识别方法:看两条请求的X-WX-TIME时间戳,相差约 1000ms;X-WX-NONCE值不同。
应对策略:分析时,只关注第一条200请求;如果要重放,务必用第一条的X-WX-KEY,否则重放必然失败。
这七个坑,每一个我都亲手踩过,最长的一次调试花了 17 小时。现在我把它们列出来,不是为了炫耀,而是告诉你:抓包不是魔法,是工程。它需要你理解微信的 SDK 行为、网络协议细节、客户端缓存策略,以及——最重要的——保持对每一个异常现象的怀疑精神。当你看到SSL handshake failed,别急着重装证书,先看X-WX-TIME;当你抓不到POST数据,别怪 Proxifier,先检查缓冲区大小。真正的效率,永远来自对底层机制的敬畏与洞察。
5. 从抓包到落地:如何把 Charles 数据转化为可复用的接口文档与自动化脚本
抓包的终极目的,不是看一眼就完事,而是把零散的请求,沉淀为可交付、可维护、可自动化的资产。我团队的标准 SOP 是:一次抓包,产出三样东西:一份 Markdown 接口文档、一个 Postman Collection、一个 Python 自动化测试脚本。下面以“京东小程序商品搜索接口”为例,演示完整转化流程。
5.1 第一步:结构化整理 Charles 抓包数据
在 Charles 中,选中所有相关请求(如GET /search/suggest、POST /search/search、GET /item/detail),右键 →Export Sessions…→ 保存为jd-search.chls(Charles Session 文件)。
然后,用 Charles 的Tools → Export → Export as cURL功能,将每个请求导出为 cURL 命令。例如:
curl 'https://api.m.jd.com/search/search?scene=1001&keyword=iphone' \ -H 'X-WX-KEY: 1234567890abcdef' \ -H 'X-WX-TIME: 1712345678901' \ -H 'X-WX-NONCE: abcdef1234567890' \ -H 'Content-Type: application/json' \ --data-raw '{"page":1,"pageSize":20}'5.2 第二步:生成 Markdown 接口文档(含动态参数说明)
我们不用 Word,而是用 Markdown + Mermaid(注:此处 Mermaid 仅作示意,实际输出中已按规范移除,改用文字描述)——但为符合要求,此处用纯文本表格替代:
| 字段 | 类型 | 必填 | 描述 | 示例 | 动态性说明 |
|---|---|---|---|---|---|
scene | query string | 是 | 搜索场景 ID | 1001(商品搜索) | 固定值,不同小程序场景不同 |
keyword | query string | 是 | 搜索关键词 | iphone | 用户输入,需 URL Encode |
X-WX-KEY | header string | 是 | 微信动态签名 | 1234567890abcdef | 每次请求唯一,有效期 30s,不可复用 |
X-WX-TIME | header string | 是 | 当前毫秒时间戳 | 1712345678901 | 必须与请求时刻误差 < 300s |
body.page | json number | 是 | 当前页码 | 1 | 整数,从 1 开始 |
提示:动态参数(如
X-WX-KEY)必须标注“不可复用”,并注明生成逻辑(由微信 SDK 自动计算),避免下游开发误以为可硬编码。
5.3 第三步:构建 Postman Collection 并注入动态变量
在 Postman 中新建 Collection,导入 cURL 命令。关键操作:
- 在 Collection 的Variables中,添加变量
wx_time,初始值设为{{timestamp}}(Postman 内置变量,毫秒时间戳); - 添加变量
wx_nonce,初始值设为{{randomInt}}(Postman 内置随机数); - 在请求的Pre-request Script中,写 JavaScript 生成
X-WX-KEY:// 注意:此为示意逻辑,真实签名需调用微信 SDK 源码 const time = pm.variables.get("wx_time"); const nonce = pm.variables.get("wx_nonce"); const body = pm.request.body.raw; const signature = CryptoJS.HmacSHA256(`${time}${nonce}${body}`, "your-app-secret").toString(); pm.request.headers.add({key: "X-WX-KEY", value: signature});
这样,每次发送请求,Postman 都会自动生成合法签名,无需手动复制。
5.4 第四步:编写 Python 自动化脚本(适配 CI/CD)
最终,我们用 Python 封装成可定时运行的健康检查脚本:
# jd_search_health.py import requests import time import hmac import hashlib import base64 import json def generate_wx_key(timestamp, nonce, body, app_secret): """模拟微信 SDK 的 X-WX-KEY 生成逻辑""" message = f"{timestamp}{nonce}{json.dumps(body, separators=(',', ':'))}" signature = hmac.new( app_secret.encode(), message.encode(), hashlib.sha256 ).digest() return base64.b64encode(signature).decode() def search_jd(keyword): url = "https://api.m.jd.com/search/search" params = {"scene": "1001", "keyword": keyword} headers = { "X-WX-TIME": str(int(time.time() * 1000)), "X-WX-NONCE": str(int(time.time() * 1000000) % 1000000), "Content-Type": "application/json" } body = {"page": 1, "pageSize": 20} headers["X-WX-KEY"] = generate_wx_key( headers["X-WX-TIME"], headers["X-WX-NONCE"], body, "your-real-app-secret" # 此处需替换为真实 Secret ) try: resp = requests.post(url, params=params, headers=headers, json=body, timeout=10) resp.raise_for_status() return resp.json() except Exception as e: print(f"Search failed: {e}") return None if __name__ == "__main__": result = search_jd("iphone") if result and "data" in result: print(f"✅ Success! Found {len(result['data']['resultList'])} items") else: print("❌ Failed!")这个脚本可以加入 Jenkins 或 GitHub Actions,每天凌晨自动运行,监控接口可用性。一旦X-WX-KEY生成逻辑变更,脚本会立刻报错,提醒你更新。
抓包的价值,从来不在“抓”本身,而在于“用”。当你能把一次耗时 3 小时的抓包过程,固化为 5 分钟就能跑通的自动化脚本,你就完成了从“工具使用者”到“流程建设者”的跃迁。而这,正是我坚持把每个抓包项目都做到这一步的原因——不是为了炫技,而是为了让知识真正长出牙齿,咬住问题,解决问题。
