小程序数据抓取实战:从抓包到模拟请求的完整指南

发布时间:2026/10/16 3:56:28
小程序数据抓取实战:从抓包到模拟请求的完整指南 1. 动手之前先搞懂小程序是怎么把数据“喂”给你的很多人一听到“逆向爬虫”就脑补出一堆黑客剧情其实放到小程序这个场景里事情远没有那么玄乎。小程序本质上是一个跑在宿主App里的前端应用不管是微信小程序、某电商App内嵌小程序还是其他平台的小程序它的代码会下发到你的设备本地运行数据则通过HTTPS请求从远端接口拉取。也就是说小程序和前端的网页一样存在两条线索可以摸一是本地代码包二是网络请求链路。我一直觉得做这类分析前先建立一个认知模型很重要。小程序的数据流动大致是这样用户打开页面小程序前端代码构造一个请求带上路径、参数、请求头和可能的加密签名发给后端网关后端处理完把JSON返回前端前端渲染成你看到的界面。所谓“逆向爬虫”并不是去攻破后端数据库而是想办法把“前端代码”和“网络请求”这两层看懂然后按照它的协议规则去构造自己的请求拿回你需要的数据。这里必须先说清楚合规边界整个过程应当只针对你本人有权限使用的小程序、公开接口或已获得授权的项目目的是做技术学习、自有数据同步或公开信息采集。不要绕过登录鉴权获取非授权数据不要爆破加密算法也不要去搞支付、用户隐私这类敏感数据。把目标定义为“理解协议、复现请求”而不是“破解系统”这个方向才是安全且可持续的。对于想入门的朋友这个事情的难度其实比想象中低。小程序前端代码虽然经过打包压缩但结构上保留了大量可读信息接口路径、参数命名、甚至部分加密逻辑都直接写在JS里。再加上抓包工具的存在你不需要去逆向汇编、不需要调试原生代码只需要按部就班地做三件事搭环境、看流量、读代码。这也是我写这篇东西的初衷把整个流程拆成可以照做的步骤帮你少走弯路。2. 环境准备搭一套顺手的抓包与调试环境2.1 设备选型模拟器优先于真机想抓小程序的包第一件事是准备一台能装小程序、能配代理的设备。我的建议是优先用安卓模拟器而不是自己的主力手机。原因很现实模拟器可以随意安装证书、随意克隆环境、恢复出厂状态也方便哪怕把环境搞坏了也不影响日常使用。真机当然能抓但安卓高版本对用户证书的限制比较严格小程序一旦做了证书校验处理起来要麻烦不少。网络上常见的模拟器都行挑一个兼容性好、自带Root或不带Root都无所谓。系统版本建议选Android 7到Android 11之间的镜像太低有些小程序不兼容太高证书信任问题会多。给模拟器配个2核CPU、2GB内存就够跑小程序了因为小程序本体并不吃性能。2.2 代理配置与HTTPS证书信任抓包的核心就是让设备流量经过一个中间代理。你电脑上装一款主流的抓包代理工具手机连同一个WiFi把代理地址指向电脑IP和工具监听端口这一步基本所有工具都差不多。配置好后打开小程序代理工具里应该能看到密密麻麻的HTTPS连接。但这里有个关键点HTTPS流量默认是加密的代理工具要能看到明文就必须向设备注入自己的根证书。常规做法是把代理工具生成的证书文件传到模拟器里在系统设置中安装为CA证书。多数小程序对用户证书没什么校验装上就能解密流量。需要注意的是Android 7以上默认不信任用户证书这时候要么把证书装进系统证书目录要么选择一个将用户证书直接视为系统证书的模拟器镜像或者干脆在系统设置里手动调整。我在实际操作中踩过最大的坑是证书装好了代理也配好了但小程序就是报网络错误。查了半天发现是代理工具没开启HTTPS解密只做了TCP转发。这个选项一般叫“Enable HTTPS Traffic Decryption”之类一定要勾上否则你只能看到连接看不到内容。2.3 按域名筛选流量打开小程序后代理工具里会混入大量无关请求宿主App自身的接口、统计SDK上报、图片资源加载、甚至广告请求。这时候不要慌先在小程序里多操作几个页面把你要分析的功能触发一遍然后回到代理工具里按域名过滤。怎么判断哪个域名是目标呢看路径特征。大部分小程序的业务接口域名会带api、gw、svc等关键字或者和小程序名称、品牌相关。筛选完域名后把请求列表按时间排序对照自己在界面上操作的步骤基本就能锁定哪几个请求对应哪个功能。例如你在小程序里搜索了一个关键词那么列表里那个POST请求、JSON参数里带着你输入关键词的就是核心数据接口。把这个请求完整记录下来后面每一步分析都围绕它展开。3. 挖出小程序前端代码本地包获取与静态分析3.1 先找到小程序包文件抓包只能让你看到请求长什么样但请求里的参数是怎么来的、加密签名是怎么算的这些还得回到前端代码里找。小程序运行时会从服务器拉取代码包缓存到宿主App的本地目录中。对安卓模拟器来说这些包文件通常存放在/data/data/某个宿主App包名目录下的特定子目录里文件名后缀可能是.wxapkg或类似格式。拿到这个文件后直接改后缀处理一下就能看到一个二进制结构里面其实是一个打包文件包含编译后的JS逻辑、模板文件、样式文件和静态资源。小程序的代码包做了轻量级的混淆但并不是那种无法阅读的原生代码。你可以搜一下现成的解析工具把包解开成一个文件夹然后用编辑器打开里面的JS文件。这里有个提醒如果模拟器没有Root可能看不到/data/data目录。解决方法是选一个自带Root权限的模拟器或者在设置里开Root然后用文件管理器或adb命令把包拷贝出来。我的习惯是开一个独立文件夹存放解析出来的包不同版本、不同日期分开存方便对比小程序迭代前后代码变化。3.2 代码里最值得搜的几个关键词解包之后直接肉眼读大量JS是很低效的。正确姿势是把JS文件丢进编辑器的全局搜索里按照优先级搜索以下关键词https://直接定位所有接口域名和完整路径api接口路径关键字appId、appid、mch_id商户或应用标识sign、signature、token加密签名相关encrypt、decrypt、AES、RSA、MD5加密逻辑线索header、Cookie、Authorization请求头生成逻辑搜到接口域名后对照抓包工具里的请求很快就能把某段代码和某个请求对应起来。这就是“从流量反推代码位置”的经典方法。3.3 顺着调用关系找参数来源光看到接口路径还不够你得搞清楚请求里的每个参数是在哪里拼出来的。小程序的JS通常是模块化的接口封装会集中在一个request工具函数里。找到这个函数你就能看到统一的请求头拼接逻辑、公共参数注入逻辑、签名计算逻辑。之后随便点开一个具体的业务接口文件看它怎么调用request就能把参数来源串起来。举个例子如果某个GET请求有一个timestamp参数代码里多半是Date.now().toString()生成的如果有一个sign参数代码里大概率会有一个函数对参数做了排序拼接再哈希。你不需要完全读懂整份项目代码只需要沿着“业务文件-request封装-公共参数方法”这条线走就能覆盖大部分需求。4. 抓到数据入口接口请求的完整构成与参数识别4.1 一个典型请求长什么样先看一个典型的小程序接口请求长什么样。假设某个小程序里的商品列表是这样一个POST请求POST https://api.example.com/product/list HTTP/1.1 Host: api.example.com Content-Type: application/json User-Agent: Mozilla/5.0 ... X-App-Id: wx1234567890 X-Token: eyJhbGciOi... X-Sign: 3f8a2b...请求体是JSON{ page: 1, pageSize: 20, keyword: 蓝牙耳机, timestamp: 1699999999 }这类请求有一个特点大多数参数都不是用户直接输入的而是前端代码自己生成的。X-Token常用于身份标识X-Sign用于防篡改timestamp用来防重放。抓包之后不要急着复制粘贴请求因为简单重放往往会被服务器拒绝原因就是你复制下来的X-Sign是旧的、过期了。4.2 加密参数常见的三种处理方式小程序接口里最常见的加密手段大致就三种第一种是普通签名把请求参数按key排序后拼接成字符串加上一个密钥再算MD5或SHA系列哈希。这类实现最简单密钥常常明晃晃写在JS里全局搜索sign就能看到。第二种是对称加密用AES或DES对请求体或响应体加密密钥同样会出现在前端代码里。你要做的就是把密钥和加密模式找出来在本地用同样算法复现。第三种是非对称加密配合动态密钥比如客户端生成一个随机AES密钥再用RSA公钥加密后传给服务端。这种情况稍微麻烦一点但只要密钥生成逻辑在前端它仍然是可复现的。在实际分析中不要试图去“破解”加密算法那是绕远路。更高效的做法是找到前端代码里那个计算签名的函数然后原封不动地把这套逻辑搬到你的爬虫脚本里。前端能做到的事情你在脚本里用同样的计算过程做一遍服务器根本分辨不出来。4.3 用脚本模拟一次请求把请求头和参数逻辑都理清楚后验证方式很简单写一个小脚本完全按照前端代码的逻辑生成签名然后发起请求看返回是否和抓包里的一致。这里给一段我常用的Python请求骨架不针对具体小程序只是演示思路import requests import hashlib import time import json def make_sign(params, secret): # 参数排序拼接 keys sorted(params.keys()) raw .join(f{k}{params[k]} for k in keys) secret return hashlib.md5(raw.encode(utf-8)).hexdigest() params { page: 1, pageSize: 20, keyword: 蓝牙耳机, timestamp: int(time.time()) } # 密钥从JS代码中定位这里是示意 secret from_js_code params[sign] make_sign(params, secret) headers { X-App-Id: wx1234567890, X-Token: your_token_from_session, Content-Type: application/json } resp requests.post( https://api.example.com/product/list, jsonparams, headersheaders, timeout10 ) print(resp.status_code) print(resp.text[:500])这里特别要提醒一件事拿到一个接口的成功返回不代表万事大吉很多小程序会校验请求头里的User-Agent、Referer甚至校验某个自定义header是否包含特定格式的设备指纹。如果第一次模拟请求返回403或业务错误码不要盲目改参数先对照抓包里的原始请求逐个头去比对找出缺了什么。5. 从接口到稳定采集爬虫落地要过的几道关5.1 登录态与Token的维护策略绝大多数小程序不会让你匿名翻数据接口里那个X-Token或Cookie对应的就是一个用户身份。如果你要长期采集数据就得先解决登录态的获取和保活问题。最简单的办法是人工登录一次小程序从抓包里拿出有效的Token先看看有效期是多久。有的Token有效只有几分钟有的是几天。如果有效期短就得考虑模拟登录流程找到登录接口复现账号密码或手机号验证码的请求流程。但这里又涉及到一个合规问题——用自动化方式登录属于平台条款中常说的非正常访问行为建议只在个人技术验证和授权环境下使用不要拿去批量注册或恶意采集。我在操心采集稳定性时一般采取这种策略优先用真实账号配合人工操作来维持会话爬虫只负责从本地配置读取Token不主动触发登录接口。当Token过期时做一个可控的告警或暂停再由人工重新获取Token填入配置。这种方式虽然不够“全自动”但稳定性和安全性都高很多。5.2 频率控制别把自己送进风控名单小程序后端对请求频率往往有限制而且比Web端更容易触发风控因为小程序的前端代码是固定的请求规律相对一致。如果你的爬虫以远超人类操作的速度连续请求触发频率限制几乎是必然的。比较稳妥的做法是把请求间隔设置在一个“看起来像人”的范围内。我常用的参数是单次请求后随机休眠1至3秒每采集100条数据后增加一次5秒的中场休息。并发方面哪怕是异步请求同时打开的连接数也不要超过3到5个。看起来效率不高但胜在稳定连续跑几个小时不出问题。如果你需要更大数据量那就拉长时间线而不是提高并发这是最直接的经验。5.3 数据存增量与去重把接口返回的数据直接落库不够因为下一次请求可能返回同样的数据。在小程序这种数据经常动态变化的场景里你需要设计一个主键用来去重比如商品ID、内容ID或信息唯一标识。每次请求后用主键检查库里是否已存在不存在则插入存在则看更新时间和内容哈希决定是否更新。另外一个容易忽略的点是分页接口的终止条件。很多分页接口返回的JSON里有hasMore、total或totalPages字段但有些接口比较懒只返回当前页数据不告诉你还有没有下一页。这时候就只能通过请求下一页后判断返回列表是否为空来终止。这种接口要小心死循环建议设置一个最大页数保护比如页数超过500就强制停止。5.4 处理接口返回里的加密数据有些小程序不光请求带签名连响应体都是加密的。抓包时候看到{data:ciphertext...}这种结构说明前端拿到响应后还要做一次解密。这时候你就回到JS代码里搜索响应处理逻辑中的解密代码找到算法和密钥然后在爬虫脚本里按同样方式解密。我遇到过最麻烦的一种情况是解密后的数据里还带一层动态字段字段名是拼音缩写或随机字母不通过抓包对照很难猜到含义。遇到这种我的经验是多抓几种不同场景的包比如搜索不同关键词、翻不同页面把返回字段变化规律记录下来再去代码里搜索这些字段名基本都能定位到对应的渲染逻辑。6. 实战中踩过的坑排查思路与避坑技巧汇总6.1 抓包能看见连接但看不到任何内容这是最常见的问题十有八九是HTTPS解密没开或证书没装对。先检查代理工具里的解密开关再看模拟器系统设置里证书是否显示“已信任”。还有一个隐蔽原因模拟器的系统时间不对导致证书校验失败。把模拟器时间改为自动同步就能解决。6.2 小程序使用了客户端证书绑定SSL Pinning有些小程序做了SSL证书校验你在代理工具里能看到TLS握手失败或直接连接被关闭。这时候常规抓包工具就失效了。比较常见的应对手段分两个层级一是用支持脚本注入的调试工具来Hook代码绕过证书校验逻辑二是直接跳过流量分析转而在模拟器里通过文件系统分析前端代码手动构造请求。不做这一步也可以很多公开数据接口根本不做SSL Pinning授权范围内可以直接用代理抓包。6.3 代码解析出来的JS是压缩成一行的大文件压缩后的JS确实恶心但不要急。先把格式化工具打开将代码展开成可读的多行结构然后再去搜索关键字。格式化后变量名仍然是简写比如a、b、c但字符串常量、接口路径、密钥这些内容是不会被混淆的搜索字符串仍然有效。如果实在绕不开逻辑混淆就回到抓包里看具体请求确定要分析的参数后再用编辑器搜索该参数名的上下文。6.4 请求已经模拟成功了但数据量一多就开始报错这种情况基本就是频率太高触发了风控。处理办法不是去换IP而是先降低频率、加长间隔。如果仍然报错可以试着清理一下请求头里非必需的header比如某些设备指纹字段减少被服务器用于关联分析的特征点。另外检查一下你的请求是否严格遵守了HTTP协议比如Content-Length、Connection头是否正确很多服务端的风控系统会先判断请求是否来自真实客户端HTTP协议不规范的请求更容易被标记。6.5 小程序里嵌了网页web-view流量却抓不到部分小程序的复杂页面会直接用web-view加载一个H5网页。这些网页流量通常不走小程序的网络栈但在代理工具里仍然可见只是域名和请求风格和小程序业务接口完全不同。如果你要抓的是web-view里的数据思路就要切换到Web爬虫方向比如分析H5页面的JS、接口和资源加载方法套路和小程序分析其实是相似的。唯一要注意的是不要混淆了两种体系下的登录态H5页面的Cookie和小程序的Token往往是两套东西。最后分享两个实用习惯做小程序信息获取这么久我最大的体会有两点。第一抓包和代码分析是互相印证的关系不要只盯着某一个。看到接口后再去代码里找这个接口的调用位置比单纯看代码高效得多而看代码里对参数的处理又能反过来帮你理解抓包中那些奇怪字段的来源。第二一定要养成留底的习惯。每分析一个小程序就单独建一个目录把解包后的代码、关键请求截图、Token配置说明、签名算法整理成文档过几个月接口升级了你还能快速定位到哪些逻辑需要修改。我见过太多人把时间耗在重复踩坑里而不是把分析资产沉淀下来。这套流程跑通之后你会发现本质上做的事情和写一个普通爬虫没太大区别核心是“理解协议”而不是“破解系统”。在这条路上走得稳的人靠的都是细致的观察和反复验证而不是什么黑魔法。