公众号爬虫入门:原理与抓包
本文是微信公众号爬虫实战的开篇。在编写爬虫之前,需要先理解网络爬虫的基本原理,掌握发送 HTTP 请求的 Requests 库,并学会用 Fiddler 抓包分析公众号的请求过程。这三块是后续抓取、存储、分析的基础。
一、爬虫的基本原理
爬虫(Web Crawler)本质上就是模拟浏览器的行为,向目标服务器发送 HTTP 请求并解析返回的数据。微信公众号文章同样遵循这一原理:公众号的文章数据最终通过 HTTP 接口从微信服务器返回,爬虫要做的是找到这些接口并模拟请求。
公众号文章的来源主要是两类接口:
- 网页版接口(
mp.weixin.qq.com):通过浏览器访问公众号历史消息页,页面中的 JS 会调用profile_ext等接口加载文章列表。- 客户端接口:PC 端或手机端微信客户端内置的接口(如
appmsgpublish)。无论哪种接口,返回的都是 JSON 格式的数据,其中包含文章标题、链接、封面、摘要等信息。爬虫的任务就是定位这些接口、构造请求参数、解析返回的 JSON。
抓包是爬虫的关键技能
抓包(Packet Capture)是指拦截客户端与服务器之间的网络请求,查看请求的 URL、请求头(Header)、请求体(Body)以及服务器返回的数据。对于微信公众号爬虫,抓包几乎是必备技能,因为:
- 微信接口的完整 URL 和参数往往埋藏在 JS 代码中,直接阅读源码成本高。
- 接口需要特定的 Cookie、token 等凭证,这些只能通过抓包获得。
- 返回数据的具体字段需要实际观察才能确定。
常见的抓包工具有 Fiddler、Charles、mitmproxy 等。由于手机端微信已实施 SSL Pinning,无法直接抓包手机端 HTTPS 流量,因此推荐使用 PC 端微信配合 Fiddler 抓包(详见下文第三部分)。
二、Requests:Python 发送 HTTP 请求的利器
Requests 是 Python 中最流行的 HTTP 请求库,封装了 urllib 的底层细节,提供简洁的 API。在编写爬虫时,用 Requests 模拟浏览器发送请求是最常见的做法。
安装
pip install requests发送 GET 请求
import requests
resp = requests.get("https://www.baidu.com")
print(resp.status_code) # 状态码,200 表示成功
print(resp.text) # 响应正文(HTML/JSON)发送带参数的 GET 请求
很多接口通过 URL 查询参数传递数据,可以用 params 字典传入:
url = "https://mp.weixin.qq.com/mp/profile_ext"
params = {
"__biz": "你的__biz",
"action": "getmsg",
"begin": "0",
"count": "10",
}
resp = requests.get(url, params=params)发送 POST 请求
微信的一些接口(如获取互动数据的 getappmsgext)使用 POST,并通过 data 或 json 传递表单/JSON 数据:
data = {
"key": "你的_key",
"pass_ticket": "你的_pass_ticket",
}
resp = requests.post(url, params=params, data=data)模拟请求头(Header)
服务器会根据 User-Agent、Referer 等请求头判断请求来源。为了模拟真实浏览器,需要设置合理的请求头:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://mp.weixin.qq.com/",
}
resp = requests.get(url, headers=headers)⚠️ 注意:不同网站的反爬策略不同,示例中使用的请求头仅是通用配置。实际抓取时,请求头应以抓包得到的真实请求头为准。
维持会话(Session)
当接口需要登录态(Cookie)时,用 requests.Session() 可以保持会话,自动携带上一次请求设置的 Cookie:
session = requests.Session()
session.headers.update(headers)
resp = session.get(url)
# 之后的请求都会自动携带会话 Cookie处理返回的 JSON
微信接口返回的数据通常是 JSON 格式,可以用 resp.json() 直接解析:
data = resp.json()
msg_list = data.get("general_msg_list") # 文章列表(JSON 字符串)一个简单爬虫示例
下面用 Requests 实现一个最简单的爬虫,抓取一个网页并提取其中的链接:
import re
import requests
resp = requests.get("https://example.com")
html = resp.text
# 用正则提取所有 href 链接
links = re.findall(r'href="([^"]*)"', html)
print(links)⚠️ 免责提示:示例仅为教学演示,抓取时应遵守目标网站的 robots 协议和相关法律法规,不要对目标站点造成压力。
三、使用 Fiddler 抓包分析公众号请求过程
Fiddler 是一个 HTTP 调试代理工具,可以拦截并查看客户端发出的所有 HTTP/HTTPS 请求。抓取公众号请求的通用流程如下。
抓包环境搭建
由于手机端微信已实施 SSL Pinning,Fiddler 无法直接解密手机端微信的 HTTPS 流量。因此推荐以下替代方案:
- PC 端微信 + Proxifier:在 Windows/Mac 上运行 PC 版微信,配合 Proxifier 将微信流量代理到 Fiddler,从而抓取 PC 端微信的请求。
- 浏览器访问:在浏览器中打开
mp.weixin.qq.com并登录,直接抓取网页版公众号接口(如profile_ext)。 - Charles / mitmproxy:这些工具同样可用,但同样受手机端 SSL Pinning 限制,更适合抓取 PC 端或浏览器流量。
💡 现状说明(2024-2026):微信生态对抓包的防护在持续加强。手机端 HTTPS 流量因 SSL Pinning 无法直接抓取;接口参数(
key、pass_ticket、appmsg_token等)均有有效期且频繁变动。每次抓取前都需要实时抓包获取最新参数,这是公众号爬虫的常态。
抓包步骤
以 PC 端微信 + Fiddler 为例:
- 启动 Fiddler,开启 HTTPS 解密(Tools → Options → HTTPS,勾选 Decrypt HTTPS traffic)。
- 用 Proxifier 将 PC 端微信进程的流量指向 Fiddler 代理(127.0.0.1:8888)。
- 在 PC 端微信中打开目标公众号的历史消息页。
- 在 Fiddler 中筛选
mp.weixin.qq.com的请求,找到加载文章列表的接口(PC 端为appmsgpublish,网页版为profile_ext)。 - 选中该请求,在 Inspectors 面板查看完整的 URL、Header、Body 以及返回的 JSON。
用 Requests 复现抓包请求
抓到请求后,把其中的 URL、Header、Cookie、参数复制到 Requests 代码中即可复现:
import requests
import json
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://mp.weixin.qq.com/",
"Cookie": "你的_cookie=xxx; wap_sid2=xxx; ...", # 从 Fiddler 拷贝
})把 Fiddler 看到的真实参数填进去,就能在代码里稳定复现抓包请求,无需每次手动操作手机。
可运行示例:PC 端微信 + requests 抓取历史文章
手机端微信因 SSL Pinning 无法直接抓包,但 PC 端微信(Windows/Mac 客户端)配合 Proxifier/Fiddler 可以正常抓包。抓包核心目标是公众号历史文章接口 appmsgpublish(电脑端)或 profile_ext(网页版)。下面以 PC 端微信 + Proxifier + Fiddler 为例,给出一个可直接运行的最小示例(需替换你自己的 Cookie 与参数):
import requests
import json
# 1. 在 PC 端微信中打开目标公众号的历史消息页,用 Fiddler 抓到 appmsgpublish 请求
# 2. 复制该请求的 URL、Header、Body 中你自己的 Cookie / key / pass_ticket 等参数到下方
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://mp.weixin.qq.com/",
# 替换为从 Fiddler 拷贝的 Cookie
"Cookie": "你的_cookie=xxx; wap_sid2=xxx; ...",
})
# 从 Fiddler 拷贝的历史文章接口地址(PC 端微信返回 JSON,含 general_msg_list)
url = "https://mp.weixin.qq.com/mp/appmsgpublish"
params = {
"__biz": "你的__biz", # 公众号唯一标识,从抓包 URL 获取
"sub": "news", # 固定值
"search_field": "null",
"begin": "0", # 分页起点,翻页时改为 上一个 begin + 每页数量
"count": "10", # 每页数量
"query": "",
"token": "你的_token",
"lang": "zh_CN",
"f": "json",
"ajax": "1",
}
data = {
"key": "你的_key", # 从抓包请求中获取
"pass_ticket": "你的_pass_ticket",
"appmsg_token": "你的_appmsg_token", # 有效期为 2-4 小时,失效需重新抓包
"x5": "0",
"f": "json",
}
resp = session.post(url, params=params, data=data)
data_json = resp.json()
# 3. 解析返回的文章列表(字段以实际抓包返回为准)
if data_json.get("general_msg_list"):
msg_list = json.loads(data_json["general_msg_list"])["list"]
for item in msg_list:
comm_msg_info = item.get("comm_msg_info", {})
app_msg_ext_info = item.get("app_msg_ext_info", {})
print({
"title": app_msg_ext_info.get("title"),
"link": app_msg_ext_info.get("content_url", "").replace("&", "&"),
"datetime": comm_msg_info.get("datetime"),
})
# 4. 翻页:将 params["begin"] 累加 count,循环执行上述请求即可抓取全部历史文章说明:
appmsgpublish(PC 端)与profile_ext(网页版)返回结构不同,字段以你抓包到的实际 JSON 为准。token、key、pass_ticket、appmsg_token均有有效期,失效后重新抓包获取即可复用同一段代码。- 建议控制抓取频率,避免触发风控。
小结
本节完成了公众号爬虫的三个基础技能:
- 原理:理解公众号文章通过 HTTP 接口返回,爬虫需要定位接口并模拟请求。
- Requests:掌握 GET/POST、请求头、Session、JSON 解析等核心用法。
- Fiddler 抓包:学会搭建 PC 端微信抓包环境,抓取并复现公众号接口请求。
下一节将进入正式实战,抓取公众号的历史文章并存储数据。
版本差异(爬虫技术栈 → 当前版本)
| 库 | 本文编写时 | 当前稳定版 |
|---|---|---|
requests | 2.28/2.31 | 2.32.x |
Scrapy | 1.x/2.0 | 2.11.x(API 稳定) |
httpx | 0.24 | 0.28.x |
Playwright | 1.3x | 1.6x(Python 版) |
lxml/BeautifulSoup | 旧版 | 保持稳定 |
| Python | 3.8-3.12 | 3.14(推荐) |
本文讲解的爬虫原理(HTTP、解析、反爬、存储)与核心 API 在最新版本中成立;注意 Python 3.9 及以下已 EOL,新项目使用 3.13/3.14。