一、引言很多刚接触爬虫的开发者都会有一个误区觉得微信小程序爬虫和普通网页爬虫差不多只要能抓包就能拿到数据。但真正动手的时候才发现小程序的接口不仅有严格的HTTPS证书校验请求参数和响应数据还经常被加密甚至还有复杂的签名验证机制普通的requests请求根本行不通。我当初第一次尝试爬取某电商小程序的时候光是绕过证书校验就花了两天时间后来又卡在了AES加密的响应数据上前前后后折腾了一周才终于拿到了想要的数据。踩了无数坑之后我总结出了一套通用的微信小程序爬虫方法论从零基础的环境配置到复杂的接口加密破解一步步带你搞定小程序数据采集。本文不会讲那些空洞的理论所有内容都来自实战经验。只要你有基本的Python基础跟着本文的步骤走就能在半天内写出一个能正常运行的小程序爬虫。二、微信小程序爬虫的核心难点微信小程序和普通网页的运行机制完全不同这也导致了它的反爬门槛比普通网页高得多。普通网页爬虫发送HTTP请求解析HTML/JSON提取数据微信小程序爬虫绕过证书校验抓包分析接口反编译小程序代码破解加密逻辑模拟请求参数解密响应数据提取数据小程序爬虫的核心难点主要集中在以下四个方面HTTPS证书校验微信内置了证书白名单普通的抓包工具证书会被拒绝接口参数加密几乎所有重要接口都有签名参数防止请求被篡改响应数据加密敏感数据会用AES等算法加密抓包只能看到乱码设备指纹检测会收集设备信息同一设备请求过多会被封禁三、环境准备与基础抓包3.1 工具准备我们需要准备以下工具Charles/Fiddler抓包工具推荐使用Charles夜神模拟器安卓模拟器方便配置证书和调试Xposed框架用于绕过微信的证书校验JustTrustMe模块禁用所有SSL证书校验wxappUnpacker小程序反编译工具3.2 证书校验绕过这是小程序爬虫的第一道坎也是最容易卡住新手的地方。安卓7.0以上系统默认不信任用户安装的证书而微信只信任系统证书。最稳定的解决方案使用夜神模拟器安卓7.1版本 Xposed JustTrustMe。这个组合可以绕过几乎所有APP的证书校验包括微信。具体步骤安装夜神模拟器并开启ROOT权限安装Xposed框架和JustTrustMe模块重启模拟器确保模块生效配置模拟器的代理指向电脑的Charles在Charles中开启SSL代理完成以上步骤后打开微信任意小程序就能在Charles中看到完整的HTTPS请求和响应了。3.3 抓包分析接口抓包成功后我们需要分析哪些接口是我们需要的。通常可以通过以下特征来判断请求方法为POSTContent-Type为application/json响应数据包含我们需要的字段请求URL中包含api、v1、v2等关键词这里有一个小技巧在Charles中设置断点然后在小程序中进行操作就能快速定位到对应的接口。四、核心接口加密破解这是小程序爬虫最关键的部分。绝大多数小程序都会使用以下三种加密方式中的一种或多种。4.1 MD5签名破解MD5签名是最常见也是最简单的加密方式。通常的做法是将所有请求参数按照一定顺序拼接然后加上一个固定的密钥最后计算MD5值作为sign参数。破解步骤使用wxappUnpacker反编译小程序nodewuWxapkg.js 小程序包名.wxapkg在反编译后的js文件中搜索sign、“md5”、signature等关键词找到签名生成函数分析参数拼接顺序和密钥用Python实现相同的签名逻辑实战代码示例importhashlibdefgenerate_sign(params,secret_key):生成MD5签名# 将参数按键名升序排序sorted_paramssorted(params.items())# 拼接参数sign_strfork,vinsorted_params:sign_strf{k}{v}# 加上密钥sign_strfkey{secret_key}# 计算MD5returnhashlib.md5(sign_str.encode(utf-8)).hexdigest().upper()4.2 AES响应数据解密很多小程序会将敏感的响应数据用AES算法加密抓包只能看到一串Base64编码的乱码。破解步骤反编译小程序搜索AES、“encrypt”、decrypt等关键词找到解密函数提取AES密钥和IV注意密钥和IV通常是固定的或者由某个固定字符串生成用Python的Crypto库实现解密实战代码示例importbase64fromCrypto.CipherimportAESfromCrypto.Util.Paddingimportunpaddefaes_decrypt(encrypted_data,key,iv):AES-CBC模式解密# 解码Base64encrypted_bytesbase64.b64decode(encrypted_data)# 创建AES解密器cipherAES.new(key.encode(utf-8),AES.MODE_CBC,iv.encode(utf-8))# 解密并去除填充decrypted_bytesunpad(cipher.decrypt(encrypted_bytes),AES.block_size)# 转换为字符串returndecrypted_bytes.decode(utf-8)4.3 动态密钥处理有些比较严格的小程序会使用动态密钥每次请求的密钥都不一样。这种情况下我们需要找到密钥的获取接口先请求密钥接口获取当前密钥再用这个密钥加密请求参数或解密响应数据五、完整Python爬虫实现现在我们将前面的所有步骤整合起来实现一个完整的小程序爬虫。importrequestsimporthashlibimportbase64importtimeimportrandomfromCrypto.CipherimportAESfromCrypto.Util.PaddingimportunpadclassWxAppSpider:def__init__(self):self.sessionrequests.Session()# 从抓包中获取的基础请求头self.base_headers{User-Agent:Mozilla/5.0 (Linux; Android 7.1.2; SM-G955N Build/N2G48H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Mobile Safari/537.36 MicroMessenger/8.0.48.2580(0x28003033) Process/appbrand0,Content-Type:application/json,Referer:https://servicewechat.com/wx1234567890abcdef/12/page-frame.html}# 从反编译中获取的加密密钥self.sign_keyyour_sign_keyself.aes_keyyour_aes_key_16bytesself.aes_ivyour_aes_iv_16bytesdefgenerate_sign(self,params):生成MD5签名sorted_paramssorted(params.items())sign_strfork,vinsorted_params:sign_strf{k}{v}sign_strfkey{self.sign_key}returnhashlib.md5(sign_str.encode(utf-8)).hexdigest().upper()defaes_decrypt(self,encrypted_data):AES解密响应数据encrypted_bytesbase64.b64decode(encrypted_data)cipherAES.new(self.aes_key.encode(utf-8),AES.MODE_CBC,self.aes_iv.encode(utf-8))decrypted_bytesunpad(cipher.decrypt(encrypted_bytes),AES.block_size)returndecrypted_bytes.decode(utf-8)defget_goods_list(self,page1,page_size20):获取商品列表urlhttps://api.example.com/wxapp/goods/list# 构造请求参数params{page:page,pageSize:page_size,timestamp:int(time.time()*1000),nonce:.join(random.choices(0123456789abcdef,k16))}# 添加签名params[sign]self.generate_sign(params)try:responseself.session.post(url,jsonparams,headersself.base_headers,timeout10)ifresponse.status_code200:resultresponse.json()ifresult[code]0:# 解密数据encrypted_dataresult[data]decrypted_dataself.aes_decrypt(encrypted_data)returndecrypted_dataelse:print(f请求失败:{result[msg]})else:print(f请求失败状态码:{response.status_code})exceptExceptionase:print(f请求异常:{e})returnNone# 使用示例if__name____main__:spiderWxAppSpider()forpageinrange(1,6):print(f正在爬取第{page}页...)dataspider.get_goods_list(page)ifdata:print(f第{page}页爬取成功)# 这里可以添加数据保存逻辑else:print(f第{page}页爬取失败)# 随机延迟模拟人类行为time.sleep(random.uniform(1,3))六、常见问题与反反爬策略证书校验绕过失败确保JustTrustMe模块正确安装并启用使用安卓7.1及以下版本的模拟器加密参数变化定期反编译小程序检查加密逻辑是否有更新请求频率限制添加随机延迟使用代理池轮换IP设备指纹检测模拟不同的设备信息随机化User-Agent和请求头登录态失效定期更新Cookie和Token保持登录状态七、总结微信小程序爬虫虽然比普通网页爬虫复杂但只要掌握了正确的方法其实并没有想象中那么难。核心思路就是先绕过证书校验抓包然后反编译小程序找到加密逻辑最后用Python模拟相同的加密和解密过程。需要特别提醒的是本文仅供技术研究使用。请遵守《网络安全法》和相关法律法规不要爬取他人的敏感数据不要将爬虫技术用于非法用途。尊重他人的知识产权和数据安全才能让技术发挥真正的价值。
微信小程序爬虫零基础实战:抓包+接口加密破解+动态数据全流程
发布时间:2026/6/19 1:01:33
一、引言很多刚接触爬虫的开发者都会有一个误区觉得微信小程序爬虫和普通网页爬虫差不多只要能抓包就能拿到数据。但真正动手的时候才发现小程序的接口不仅有严格的HTTPS证书校验请求参数和响应数据还经常被加密甚至还有复杂的签名验证机制普通的requests请求根本行不通。我当初第一次尝试爬取某电商小程序的时候光是绕过证书校验就花了两天时间后来又卡在了AES加密的响应数据上前前后后折腾了一周才终于拿到了想要的数据。踩了无数坑之后我总结出了一套通用的微信小程序爬虫方法论从零基础的环境配置到复杂的接口加密破解一步步带你搞定小程序数据采集。本文不会讲那些空洞的理论所有内容都来自实战经验。只要你有基本的Python基础跟着本文的步骤走就能在半天内写出一个能正常运行的小程序爬虫。二、微信小程序爬虫的核心难点微信小程序和普通网页的运行机制完全不同这也导致了它的反爬门槛比普通网页高得多。普通网页爬虫发送HTTP请求解析HTML/JSON提取数据微信小程序爬虫绕过证书校验抓包分析接口反编译小程序代码破解加密逻辑模拟请求参数解密响应数据提取数据小程序爬虫的核心难点主要集中在以下四个方面HTTPS证书校验微信内置了证书白名单普通的抓包工具证书会被拒绝接口参数加密几乎所有重要接口都有签名参数防止请求被篡改响应数据加密敏感数据会用AES等算法加密抓包只能看到乱码设备指纹检测会收集设备信息同一设备请求过多会被封禁三、环境准备与基础抓包3.1 工具准备我们需要准备以下工具Charles/Fiddler抓包工具推荐使用Charles夜神模拟器安卓模拟器方便配置证书和调试Xposed框架用于绕过微信的证书校验JustTrustMe模块禁用所有SSL证书校验wxappUnpacker小程序反编译工具3.2 证书校验绕过这是小程序爬虫的第一道坎也是最容易卡住新手的地方。安卓7.0以上系统默认不信任用户安装的证书而微信只信任系统证书。最稳定的解决方案使用夜神模拟器安卓7.1版本 Xposed JustTrustMe。这个组合可以绕过几乎所有APP的证书校验包括微信。具体步骤安装夜神模拟器并开启ROOT权限安装Xposed框架和JustTrustMe模块重启模拟器确保模块生效配置模拟器的代理指向电脑的Charles在Charles中开启SSL代理完成以上步骤后打开微信任意小程序就能在Charles中看到完整的HTTPS请求和响应了。3.3 抓包分析接口抓包成功后我们需要分析哪些接口是我们需要的。通常可以通过以下特征来判断请求方法为POSTContent-Type为application/json响应数据包含我们需要的字段请求URL中包含api、v1、v2等关键词这里有一个小技巧在Charles中设置断点然后在小程序中进行操作就能快速定位到对应的接口。四、核心接口加密破解这是小程序爬虫最关键的部分。绝大多数小程序都会使用以下三种加密方式中的一种或多种。4.1 MD5签名破解MD5签名是最常见也是最简单的加密方式。通常的做法是将所有请求参数按照一定顺序拼接然后加上一个固定的密钥最后计算MD5值作为sign参数。破解步骤使用wxappUnpacker反编译小程序nodewuWxapkg.js 小程序包名.wxapkg在反编译后的js文件中搜索sign、“md5”、signature等关键词找到签名生成函数分析参数拼接顺序和密钥用Python实现相同的签名逻辑实战代码示例importhashlibdefgenerate_sign(params,secret_key):生成MD5签名# 将参数按键名升序排序sorted_paramssorted(params.items())# 拼接参数sign_strfork,vinsorted_params:sign_strf{k}{v}# 加上密钥sign_strfkey{secret_key}# 计算MD5returnhashlib.md5(sign_str.encode(utf-8)).hexdigest().upper()4.2 AES响应数据解密很多小程序会将敏感的响应数据用AES算法加密抓包只能看到一串Base64编码的乱码。破解步骤反编译小程序搜索AES、“encrypt”、decrypt等关键词找到解密函数提取AES密钥和IV注意密钥和IV通常是固定的或者由某个固定字符串生成用Python的Crypto库实现解密实战代码示例importbase64fromCrypto.CipherimportAESfromCrypto.Util.Paddingimportunpaddefaes_decrypt(encrypted_data,key,iv):AES-CBC模式解密# 解码Base64encrypted_bytesbase64.b64decode(encrypted_data)# 创建AES解密器cipherAES.new(key.encode(utf-8),AES.MODE_CBC,iv.encode(utf-8))# 解密并去除填充decrypted_bytesunpad(cipher.decrypt(encrypted_bytes),AES.block_size)# 转换为字符串returndecrypted_bytes.decode(utf-8)4.3 动态密钥处理有些比较严格的小程序会使用动态密钥每次请求的密钥都不一样。这种情况下我们需要找到密钥的获取接口先请求密钥接口获取当前密钥再用这个密钥加密请求参数或解密响应数据五、完整Python爬虫实现现在我们将前面的所有步骤整合起来实现一个完整的小程序爬虫。importrequestsimporthashlibimportbase64importtimeimportrandomfromCrypto.CipherimportAESfromCrypto.Util.PaddingimportunpadclassWxAppSpider:def__init__(self):self.sessionrequests.Session()# 从抓包中获取的基础请求头self.base_headers{User-Agent:Mozilla/5.0 (Linux; Android 7.1.2; SM-G955N Build/N2G48H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Mobile Safari/537.36 MicroMessenger/8.0.48.2580(0x28003033) Process/appbrand0,Content-Type:application/json,Referer:https://servicewechat.com/wx1234567890abcdef/12/page-frame.html}# 从反编译中获取的加密密钥self.sign_keyyour_sign_keyself.aes_keyyour_aes_key_16bytesself.aes_ivyour_aes_iv_16bytesdefgenerate_sign(self,params):生成MD5签名sorted_paramssorted(params.items())sign_strfork,vinsorted_params:sign_strf{k}{v}sign_strfkey{self.sign_key}returnhashlib.md5(sign_str.encode(utf-8)).hexdigest().upper()defaes_decrypt(self,encrypted_data):AES解密响应数据encrypted_bytesbase64.b64decode(encrypted_data)cipherAES.new(self.aes_key.encode(utf-8),AES.MODE_CBC,self.aes_iv.encode(utf-8))decrypted_bytesunpad(cipher.decrypt(encrypted_bytes),AES.block_size)returndecrypted_bytes.decode(utf-8)defget_goods_list(self,page1,page_size20):获取商品列表urlhttps://api.example.com/wxapp/goods/list# 构造请求参数params{page:page,pageSize:page_size,timestamp:int(time.time()*1000),nonce:.join(random.choices(0123456789abcdef,k16))}# 添加签名params[sign]self.generate_sign(params)try:responseself.session.post(url,jsonparams,headersself.base_headers,timeout10)ifresponse.status_code200:resultresponse.json()ifresult[code]0:# 解密数据encrypted_dataresult[data]decrypted_dataself.aes_decrypt(encrypted_data)returndecrypted_dataelse:print(f请求失败:{result[msg]})else:print(f请求失败状态码:{response.status_code})exceptExceptionase:print(f请求异常:{e})returnNone# 使用示例if__name____main__:spiderWxAppSpider()forpageinrange(1,6):print(f正在爬取第{page}页...)dataspider.get_goods_list(page)ifdata:print(f第{page}页爬取成功)# 这里可以添加数据保存逻辑else:print(f第{page}页爬取失败)# 随机延迟模拟人类行为time.sleep(random.uniform(1,3))六、常见问题与反反爬策略证书校验绕过失败确保JustTrustMe模块正确安装并启用使用安卓7.1及以下版本的模拟器加密参数变化定期反编译小程序检查加密逻辑是否有更新请求频率限制添加随机延迟使用代理池轮换IP设备指纹检测模拟不同的设备信息随机化User-Agent和请求头登录态失效定期更新Cookie和Token保持登录状态七、总结微信小程序爬虫虽然比普通网页爬虫复杂但只要掌握了正确的方法其实并没有想象中那么难。核心思路就是先绕过证书校验抓包然后反编译小程序找到加密逻辑最后用Python模拟相同的加密和解密过程。需要特别提醒的是本文仅供技术研究使用。请遵守《网络安全法》和相关法律法规不要爬取他人的敏感数据不要将爬虫技术用于非法用途。尊重他人的知识产权和数据安全才能让技术发挥真正的价值。