FEATURED · 精选文章

微信小程序爬虫实战:抓包到数据入库的完整方案

发布时间 / 2026/9/8 10:51:34
来源 / 创域科博编辑部
栏目 / 资讯中心
微信小程序爬虫实战:抓包到数据入库的完整方案 简介微信小程序爬虫项目面向需要获取小程序商品列表数据的开发者、数据分析师与电商运营人员。压缩包内实现了一套基于模拟交互的爬虫方案支持将抓取结果写入MySQL、SQLite等数据库并提供清洗与格式化处理逻辑。资源共20个文件包含6个Python源码、5个SQL脚本、JSON配置及说明文档等整体仅1.56MB结构清晰便于二次开发。项目内含主程序、数据模型、SQL建表语句及位置切分模块代码注释清晰便于阅读同时涉及网络异常、解析失败、写入失败等常见异常处理可提高爬虫稳定性还预留了定时爬取与数据分析接口可结合实际业务进行扩展。已有98人学习下载。通过该项目可掌握小程序数据抓取的基本流程、数据库落库方式以及异常处理思路适合有一定Python基础并希望快速搭建爬虫原型的读者参考。 微信小程序爬虫这个需求最初是我在维护一个内部商城项目时冒出来的。当时运营同事每周都要把小程序后台的商品数据导出来做一次比价和库存核对可后台的导出按钮偏偏只能给出部分字段剩下全靠人肉去页面里翻。干了两周这种活之后我决定自己写个脚本把商品列表接口的数据拉下来定期写进本地数据库。跑顺之后又把它整理成了一个独立的 zip 项目包方便以后其他项目直接用。今天这篇文章就围绕这个包展开把从抓包、分析请求到模拟调用、数据入库的完整链路讲清楚。先简单说下结论这个工具的本质是一个面向微信小程序商品列表的定向采集脚本核心流程是「抓包拿到接口 → 用 requests 模拟请求 → 解析 JSON → 写入数据库」。它不需要 hook 小程序运行环境也不需要 root 或越狱设备真正的难点集中在「怎么拿到完整请求参数」和「怎么处理签名校验」这两个环节。后面我会把每个环节的排查过程、参数选择逻辑和实际踩坑记录都展开讲尽量让只写过 Python 基础脚本的读者也能照着跑通。1. 设计思路与技术选型1.1 为什么选「抓包 请求模拟」而不是 UI 自动化一开始我考虑过两条技术路线一是用 Appium 或 Airtest 这类工具驱动小程序界面模拟滑屏、点击去拿页面上的商品数据二是直接抓包定位后端接口用脚本模拟请求拿 JSON。两条路我都实际试过最后留下了后者。原因很直接。UI 自动化的确能应对一些简单的列表页但它对界面改动极其敏感——小程序发个版本按钮位置稍微一调脚本就要跟着改。而且商品列表页往往是无限下拉加载UI 自动化滚动到几百条数据时非常慢抓几千条商品可能要跑一两个小时。接口模拟则完全绕开了渲染层直接和后端做数据交互一次请求拿几十条分页循环几十次就完成全量同步速度不是一个量级。当然接口模拟的前提是你得能完整还原请求头部和参数这部分后面的抓包章节会说。如果目标小程序对请求做了很重的风控——比如绑定设备指纹、每个请求都校验时间戳签名——UI 自动化反而会更保险。但从这个 zip 包的目标场景自营商品归档、日常数据同步来看接口模拟的性价比明显更高。1.2 技术栈requests SQLite/MySQL 就够用工具的核心依赖很少只有requests和数据库驱动。为什么不用 ScrapyScrapy 的并发调度和中间件设计确实强大但在这个场景下会产生额外的维护成本——你得在项目里维护整个爬虫框架的工程结构重启、调试都不够轻量。requests 配合简单的循环和time.sleep控制请求节奏足够应付几千量级的商品数据同步出问题也容易定位。数据库选了 SQLite 和 MySQL 两个版本。SQLite 适合单机快速验证文件即数据库跑完一个脚本直接生成.db文件MySQL 适合需要多人共享数据或二次开发的场景方便直接接入已有的管理系统。我在包内用了一个配置文件切换连接方式默认走 SQLite改一行配置就能切到 MySQL。这里有一个容易被新手忽略的设计点商品列表接口返回的字段通常比数据库表字段多。比如一些平台接口会返回item_id、sku_info、category_name等冗余字段如果全量塞进数据库表表结构会非常臃肿。我建议在写入层做一层字段白名单映射只保留真正需要的核心字段后面查询和维护都会轻松很多。2. 环境配置与抓包准备2.1 抓包工具选择与安装抓包是小程序爬虫最关键的第一步。我常用的工具是 Charles 和 mitmproxy两者各有适用场景Charles 有图形界面开启 HTTPS 抓包和安装证书都方便适合初次接触抓包的新手mitmproxy 是命令行工具可以脚本化处理返回数据适合需要批量导出接口信息的场景。以 Charles 为例安装后需要做两步配置。第一步在 Charles 里开启 HTTPS 抓包并把 Charles 的根证书安装到电脑第二步把手机或 PC 端微信的网络流量指向电脑的 IP 和 Charles 的默认端口 8888。这里有个细节从微信 7.0 版本开始Android 端默认不信任用户证书需要在手机设置里手动信任 Charles 证书否则看到的一律是 TLS 握手失败。iOS 端则要在「设置-通用-关于本机-证书信任设置」里把 Charles 证书开关打开。PC 端微信小程序的抓包这里额外提醒一句。直接开着 Charles 接管系统网络流量很容易出现只能刷出公众号文章、看不到小程序请求的情况原因是 PC 端小程序走的是独立网络栈部分版本不继承系统网络设置。我当时的处理方案是在微信的启动参数里强制指定转发端口或者借助进程级网络流量重定向工具把微信进程的请求统一引到 Charles。这个方案在 Windows 和 macOS 上都验证过稳定性不错。2.2 定位商品列表接口抓包环境就绪之后打开小程序进到商品列表页不断下拉触发翻页加载Charles 里会刷出一堆请求。商品接口通常有比较明显的特征URL 中包含goods、product、item、list等关键词返回体是 JSON 而非 HTML。把所有可疑请求按路径筛选一遍再翻一页页面看是哪个请求在重复发出就基本能锁定目标接口。锁定了接口之后要把请求的关键信息完整复制出来包含三块完整的 URL含 query 参数请求头headers重点是Content-Type、Referer、User-Agent、token、sign这类自定义字段请求体如果是 POST通常是 JSON 或表单数据。在 Charles 的响应面板能看到返回体如果返回的 JSON 已经包含商品列表数据说明接口不用再二次处理如果返回的是 HTML 或加密字符串就需要进一步分析解密逻辑这个情况在第 4 节会展开。3. 核心实现从请求模拟到数据入库3.1 请求模拟与分页循环拿到完整请求信息后用 requests 模拟是水到渠成的事。先把请求头和参数写成字典然后发请求。这里最关键的是不要让脚本一上来就全量跑建议先写一个单页请求的调试版本确认返回数据和 Charles 里看到的一致再扩展成完整分页循环。我实际项目里的分页逻辑大体是这样的def fetch_goods_list(session, page, page_size20): url https://api.example.com/wxapp/goods/list headers { User-Agent: Mozilla/5.0 ..., token: cfg[token], sign: make_sign(cfg[secret], page, page_size), Content-Type: application/json, } payload { page: page, page_size: page_size, status: 1, } resp session.post(url, jsonpayload, headersheaders, timeout10) resp.raise_for_status() return resp.json()分页循环里有两个细节值得说一下。第一是循环退出条件——不能简单用for page in range(1, 10000)硬跑万一某页数据异常很容易死循环或白白消耗请求次数。我一般会在响应体里取总页数字段通常是total_page或total_count / page_size到达总页数就退出如果接口没给总页数就判断当前页返回空列表时退出。第二是请求间隔——商品列表接口对频率比较敏感我习惯在每次请求之间加time.sleep(0.5)到1秒让总请求节奏看起来更像手动操作也能减少触发风控的概率。3.2 签名与 token 的处理方式小程序接口的签名校验是绕不开的一环。最常见的做法是把请求参数按照字典序拼接加上密钥后做 MD5 或 HMAC 签名后端校验通过才返回数据。如果你发现请求头里带sign字段可以先手动抓包看看请求参数和 sign 之间的对应规律。简单的签名规则通过对比多个请求就能反推出来比如sign md5(secret sorted_params_as_string)。但如果签名逻辑写在小程序代码包里并且做过混淆逆向就比较费劲。我的经验是优先搜索「小程序 签名」相关的技术社区帖子很多平台的签名算法都有人做过分析实在不行再考虑 hook 小程序运行环境去动态获取签名——这一步会涉及更复杂的工具链不在这个 zip 包的基础能力范围内。token 的处理相对简单。通常在小程序启动后会调用一个登录接口换取 token后续所有业务请求都带上这个 token。切换用户身份或 token 过期时重新调用登录接口刷新即可。我在包里把 token 配置和登录刷新函数单独抽了一个模块设计目的是当你面对不同小程序时只改登录入口和 token 字段名不用动核心采集逻辑。3.3 数据解析与字段映射请求返回的 JSON 结构每家平台差异很大但商品列表类接口一般逃不出两种模式要么整体在data.list里要么在data.records或直接就是数组。拿到响应后先json.dumps打印出一部分确认层级结构后再做解析。在实际处理时我会把解析和入库分开。解析函数只负责把原始 JSON 转成统一的字典列表def parse_goods(data): records data.get(data, {}).get(list, []) rows [] for item in records: rows.append({ goods_id: item.get(goods_id), title: item.get(goods_name) or item.get(title), price: item.get(min_price) or item.get(price), stock: item.get(stock_num), category: item.get(category_name), }) return rows这样设计的好处是一旦目标接口换了字段名只需要改解析函数下游的入库逻辑完全不用动。字段映射这里有一个小坑价格字段在不同平台可能是「分」或「元」两种单位建议在解析层统一转成元并保留两位小数否则入库后统计金额的时候很容易差出几百倍。3.4 数据库写入与幂等设计数据库写入我用的是批量插入 去重更新的策略。对于 SQLiteINSERT INTO goods (goods_id, title, price, stock, category, updated_at) VALUES (?, ?, ?, ?, ?, datetime(now, localtime)) ON CONFLICT(goods_id) DO UPDATE SET title excluded.title, price excluded.price, stock excluded.stock, category excluded.category, updated_at excluded.updated_at;ON CONFLICT DO UPDATE本质上是做增量同步——商品存在就更新不存在就新增。这个设计在反复跑脚本时非常重要否则每次全量插入都会生成重复记录后面做数据对比时全是脏数据。如果要连 MySQL建表语句可以类似这样CREATE TABLE goods ( id INT AUTO_INCREMENT PRIMARY KEY, goods_id VARCHAR(64) UNIQUE, title VARCHAR(255), price DECIMAL(10, 2), stock INT, category VARCHAR(255), updated_at DATETIME );唯一键goods_id是幂等更新的基础没有唯一键ON DUPLICATE KEY UPDATE就无从谈起。4. 常见问题与排查技巧4.1 签名校验失败的定位思路我在实际拉数据时遇到最多的问题就是sign invalid或token expired这类报错。遇到签名失败第一步不是去看代码而是回到 Charles 重新抓一次正常请求把脚本发出的请求跟正常请求做逐字段对比。重点看三处请求头是否完全一致、参数排序规则是否正确、签名使用的密钥是否过期。如果对比下来依然摸不着头脑可以试试把请求参数里的非业务字段比如timestamp、nonce也纳入签名计算。有些小程序后端会把时间戳和随机数拼在签名内容里这类参数每次请求都在变签名结果当然也是动态的必须实时生成不能写死在配置里。4.2 返回加密数据怎么办有些接口为了防采集返回的 JSON 里data字段是一串 base64 或密文需要额外解密。这种情况先观察密文特征base64 结尾一般是AES/CBC 加密的密文长度通常是 16 的倍数。如果能定位到小程序的解密逻辑并看懂加密算法可以在 Python 里用pycryptodome库复现同样流程。但说句实话如果目标接口加密强度很高我的建议是换个思路。优先找小程序里是否还有别的未加密接口能用或者直接改用 UI 自动化方案。采集程序最大的价值在于稳定维护而不是死磕某一个被加密的接口。4.3 频繁请求触发风控围绕小程序爬虫最常见的风控表现是前几十次请求正常后面突然返回-1、blocked或验证码页面。这种基本就是单位时间内请求频率超过了阈值。我的处理方式是三板斧。第一降低请求频率把间隔拉大到 2~5 秒第二给脚本增加出口 IP 轮换能力准备一组可用 IP 轮换发起请求第三在非高峰时段运行脚本比如凌晨两三点。这三条配合起来绝大多数中小规模小程序的采集场景都能稳下来。4.4 常见问题速查表现象可能原因排查方法抓包一片空白证书未信任检查手机和 PC 的证书信任开关请求返回 404接口路径带动态参数对比抓包软件中的完整 URLsign invalid签名规则或密钥错误逐字段比对正常请求total_page 一直为 1总数字段名写错打印响应体 JSON 确认字段数据库插入重复缺少唯一键给 goods_id 加 UNIQUE运行中断token 过期增加登录刷新逻辑4.5 合法合规使用提醒最后必须说一句写爬虫一定要清楚边界。如果采集的是自己的小程序、或有明确授权的合作方系统这完全没问题如果采集公开市场的商品价格数据用于合法分析也要注意遵守平台规则和当地法律法规。擅自爬取未授权数据、绕过访问控制、用于商业竞争都可能带来法律风险。这篇文章里的技术手段请只用于你有权访问和使用的数据场景。本文还有配套的精品资源点击获取
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻