微信小程序门店数据抓包与 Python 爬虫全流程指南(以“吉祥馄饨”为例)
本文档总结了如何通过电脑端微信配合抓包工具 Reqable 获取小程序后台数据接口(API),并使用 Python 编写自动化脚本批量抓取分店名称、地址、电话、经纬度等信息并导出为 Excel 表格的完整流程。
一、 准备工作与环境要求
- 电脑端微信:登录个人微信账号(Windows 或 macOS 均可)。
- 抓包工具 Reqable:
- 下载安装并打开 Reqable。
- 确保右上角状态栏的三个图标(⌘ 系统代理、🌐 网络、🛡️ 根证书)均为绿色激活状态,且左侧显示绿点
Proxying on ...(正在监听)。
- Python 环境:安装好 Python 3.x,并安装好请求与表格处理依赖库:
pip install requests pandas openpyxl urllib3
二、 第一阶段:使用 Reqable 抓取小程序接口
1. 触发小程序网络请求
- 如果电脑微信中已经打开了目标小程序(如“吉祥馄饨”),先点击右上角
✕关闭小程序(避免读取本地缓存而不发网络请求)。 - 确保 Reqable 处于正在抓包状态(右上角按钮显示为“⏸ 暂停”)。
- 重新在微信中打开“吉祥馄饨”小程序,点击“点餐”或“切换门店”,选择目标城市(如:天津市)。
2. 从抓包列表中定位核心接口
在 Reqable 的请求列表中,会同时出现大量干扰项,可通过以下规律快速排查:
- 排除干扰项:
- 域名含
map.qq.com、gtimg.com:腾讯地图底图加载请求,忽略。 - 域名含
wxgateway.com、weixinbridge.com:微信官方日志与统计上报,忽略。
- 域名含
- 锁定目标接口:
- 重点关注应用程序为
WeChatAppEx、方法为POST或GET、类型图标为{}(JSON 格式)的业务域名请求。 - 在本案例中:
- 请求方法:
POST - 目标 URL:
https://applet.mtcbj.com/applet/api/shop/queryShopPage/v2(从路径单词shop/queryShopPage即可判断为“查询门店分页接口”)。
- 请求方法:
- 重点关注应用程序为
三、 第二阶段:提取请求报文与分析响应结构
选中目标请求后,在 Reqable 右侧面板分别提取请求信息和响应信息。
1. 提取原始请求信息(右上角面板 -> 【原始】)
用于获取请求头(重点是 token 和 user-agent)以及请求体参数(payload):
POST /applet/api/shop/queryShopPage/v2 HTTP/2
host: applet.mtcbj.com
client_version: 1.0.447
xweb_xhr: 1
client_env: release
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541f38) XWEB/25799
accept: application/json, text/plain, */*
content-type: application/json
token: b641f4440a9a4851952908dada1cbd3fM413102457627885583
referer: https://servicewechat.com/wx469fe58febd5898f/214/page-frame.html
{"shopAddressCode":"1-120000-1201","userLon":"117.19937133789062","userLat":"39.08509826660156","deliverType":"","current":1,"size":15}
- 参数解析:
shopAddressCode:城市代码(1-120000-1201代表天津市)。current:当前页码(从1开始)。size:每页返回的门店数量(默认15条)。
2. 分析响应 JSON 结构(右下角面板 -> 【响应体】)
查看服务器返回的 JSON 数据,明确分页逻辑和核心字段名称:
{
"success": true,
"code": "00000",
"msg": "成功",
"data": {
"current": 1,
"size": 15,
"total": 81,
"pages": 6,
"records": [
{
"shopId": 10003762,
"shopName": "吉祥馄饨(天津肿瘤医院店)",
"openingHoursStart": "06:30",
"openingHoursEnd": "22:30",
"tel": "15822868388",
"addressCity": "天津市天津市",
"addressDetail": "体院北环湖南里七区13号",
"posOnline": true,
"longitude": "117.18644335",
"latitude": "39.08108777"
}
]
}
}
- 核心字段对应关系:
- 总门店数:
data.total(81 家) - 总页数:
data.pages(6 页) - 门店列表数组:
data.records - 分店名称:
shopName - 详细地址:
addressDetail - 联系电话:
tel - 经纬度:
longitude/latitude
- 总门店数:
四、 第三阶段:编写并运行 Python 自动化爬虫脚本
⚠️ 运行前注意事项
在运行 Python 脚本前,建议先在 Reqable 右上角关闭 ⌘ 系统代理(或直接退出 Reqable),并在代码中加入 verify=False 忽略 SSL 证书校验,防止本地代理拦截导致报错。
完整 Python 源码 (fetch_shops.py)
import requests
import pandas as pd
import time
import urllib3
# 忽略SSL证书告警(防止本地抓包软件代理干扰)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def fetch_jixiang_shops():
url = "https://applet.mtcbj.com/applet/api/shop/queryShopPage/v2"
# 1. 请求头(重点保留 user-agent、token、content-type 和 referer)
headers = {
"client_version": "1.0.447",
"xweb_xhr": "1",
"client_env": "release",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541f38) XWEB/25799",
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"token": "b641f4440a9a4851952908dada1cbd3fM413102457627885583", # 若过期需重新抓包替换
"referer": "https://servicewechat.com/wx469fe58febd5898f/214/page-frame.html",
"accept-language": "zh-CN,zh;q=0.9"
}
all_shops = []
current_page = 1
total_pages = 1 # 初始值,第1次请求后会自动更新为实际总页数
print("🚀 开始抓取吉祥馄饨门店数据...")
while current_page <= total_pages:
# 2. 构造分页请求参数
payload = {
"shopAddressCode": "1-120000-1201", # 城市编码:天津市
"userLon": "117.19937133789062",
"userLat": "39.08509826660156",
"deliverType": "",
"current": current_page,
"size": 15
}
response = requests.post(url, headers=headers, json=payload, verify=False, timeout=10)
res_json = response.json()
if not res_json.get("success"):
print(f"❌ 第 {current_page} 页请求失败,返回信息:", res_json)
break
data = res_json.get("data", {})
total_pages = data.get("pages", 1)
total_count = data.get("total", 0)
records = data.get("records", [])
# 3. 解析单页门店列表
for shop in records:
raw_name = shop.get("shopName", "")
# 清洗出括号内的纯店名,方便与其他表格直接比对
clean_name = raw_name.replace("吉祥馄饨(", "").replace(")", "") if "吉祥馄饨(" in raw_name else raw_name
all_shops.append({
"门店ID": shop.get("shopId"),
"分店全称": raw_name,
"分店简称(用于对比)": clean_name,
"详细地址": shop.get("addressDetail"),
"联系电话": shop.get("tel"),
"营业开始": shop.get("openingHoursStart"),
"营业结束": shop.get("openingHoursEnd"),
"是否营业中": "是" if shop.get("posOnline") else "否",
"经度": shop.get("longitude"),
"纬度": shop.get("latitude")
})
print(f"✅ 已抓取第 {current_page}/{total_pages} 页,累计获取 {len(all_shops)}/{total_count} 家门店")
current_page += 1
time.sleep(0.5) # 礼貌延时 0.5 秒
# 4. 导出至 Excel
if all_shops:
df = pd.DataFrame(all_shops)
file_name = "吉祥馄饨_天津门店列表.xlsx"
df.to_excel(file_name, index=False)
print(f"\n🎉 全部抓取完成!共 {len(df)} 家门店,已保存至 【{file_name}】!")
else:
print("⚠️ 未获取到门店数据,请检查 token 是否过期。")
if __name__ == "__main__":
fetch_jixiang_shops()
五、 常见问题与扩展技巧
- 运行报错提示“未登录”或请求失败怎么办?
- 小程序的
token通常具有时效性(几小时到几天不等)。如果隔天运行失败,只需打开 Reqable 重新抓一次包,把最新的token替换到代码的headers中即可。
- 小程序的
- 如何抓取其他城市的门店?
- 在小程序左上角切换为其他城市(如“上海市”或“北京市”),在 Reqable 中查看请求体里的
shopAddressCode变成了什么编码,替换代码中的shopAddressCode即可抓取对应城市。
- 在小程序左上角切换为其他城市(如“上海市”或“北京市”),在 Reqable 中查看请求体里的
本文档由AI生成!!!
浙公网安备 33010602011771号