{T}

公众号爬虫入门:原理与抓包

本文是微信公众号爬虫实战的开篇。在编写爬虫之前,需要先理解网络爬虫的基本原理,掌握发送 HTTP 请求的 Requests 库,并学会用 Fiddler 抓包分析公众号的请求过程。这三块是后续抓取、存储、分析的基础。

一、爬虫的基本原理

爬虫(Web Crawler)本质上就是模拟浏览器的行为,向目标服务器发送 HTTP 请求并解析返回的数据。微信公众号文章同样遵循这一原理:公众号的文章数据最终通过 HTTP 接口从微信服务器返回,爬虫要做的是找到这些接口并模拟请求。

公众号文章的来源主要是两类接口:

  • 网页版接口mp.weixin.qq.com):通过浏览器访问公众号历史消息页,页面中的 JS 会调用 profile_ext 等接口加载文章列表。
  • 客户端接口:PC 端或手机端微信客户端内置的接口(如 appmsgpublish)。

无论哪种接口,返回的都是 JSON 格式的数据,其中包含文章标题、链接、封面、摘要等信息。爬虫的任务就是定位这些接口、构造请求参数、解析返回的 JSON。

抓包是爬虫的关键技能

抓包(Packet Capture)是指拦截客户端与服务器之间的网络请求,查看请求的 URL、请求头(Header)、请求体(Body)以及服务器返回的数据。对于微信公众号爬虫,抓包几乎是必备技能,因为:

  1. 微信接口的完整 URL 和参数往往埋藏在 JS 代码中,直接阅读源码成本高。
  2. 接口需要特定的 Cookie、token 等凭证,这些只能通过抓包获得。
  3. 返回数据的具体字段需要实际观察才能确定。

常见的抓包工具有 Fiddler、Charles、mitmproxy 等。由于手机端微信已实施 SSL Pinning,无法直接抓包手机端 HTTPS 流量,因此推荐使用 PC 端微信配合 Fiddler 抓包(详见下文第三部分)。

二、Requests:Python 发送 HTTP 请求的利器

Requests 是 Python 中最流行的 HTTP 请求库,封装了 urllib 的底层细节,提供简洁的 API。在编写爬虫时,用 Requests 模拟浏览器发送请求是最常见的做法。

安装

bash
pip install requests

发送 GET 请求

python
import requests

resp = requests.get("https://www.baidu.com")
print(resp.status_code)   # 状态码,200 表示成功
print(resp.text)          # 响应正文(HTML/JSON)

发送带参数的 GET 请求

很多接口通过 URL 查询参数传递数据,可以用 params 字典传入:

python
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,并通过 datajson 传递表单/JSON 数据:

python
data = {
    "key": "你的_key",
    "pass_ticket": "你的_pass_ticket",
}
resp = requests.post(url, params=params, data=data)

模拟请求头(Header)

服务器会根据 User-AgentReferer 等请求头判断请求来源。为了模拟真实浏览器,需要设置合理的请求头:

python
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:

python
session = requests.Session()
session.headers.update(headers)
resp = session.get(url)
# 之后的请求都会自动携带会话 Cookie

处理返回的 JSON

微信接口返回的数据通常是 JSON 格式,可以用 resp.json() 直接解析:

python
data = resp.json()
msg_list = data.get("general_msg_list")  # 文章列表(JSON 字符串)

一个简单爬虫示例

下面用 Requests 实现一个最简单的爬虫,抓取一个网页并提取其中的链接:

python
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 流量。因此推荐以下替代方案:

  1. PC 端微信 + Proxifier:在 Windows/Mac 上运行 PC 版微信,配合 Proxifier 将微信流量代理到 Fiddler,从而抓取 PC 端微信的请求。
  2. 浏览器访问:在浏览器中打开 mp.weixin.qq.com 并登录,直接抓取网页版公众号接口(如 profile_ext)。
  3. Charles / mitmproxy:这些工具同样可用,但同样受手机端 SSL Pinning 限制,更适合抓取 PC 端或浏览器流量。

💡 现状说明(2024-2026):微信生态对抓包的防护在持续加强。手机端 HTTPS 流量因 SSL Pinning 无法直接抓取;接口参数(keypass_ticketappmsg_token 等)均有有效期且频繁变动。每次抓取前都需要实时抓包获取最新参数,这是公众号爬虫的常态。

抓包步骤

以 PC 端微信 + Fiddler 为例:

  1. 启动 Fiddler,开启 HTTPS 解密(Tools → Options → HTTPS,勾选 Decrypt HTTPS traffic)。
  2. 用 Proxifier 将 PC 端微信进程的流量指向 Fiddler 代理(127.0.0.1:8888)。
  3. 在 PC 端微信中打开目标公众号的历史消息页。
  4. 在 Fiddler 中筛选 mp.weixin.qq.com 的请求,找到加载文章列表的接口(PC 端为 appmsgpublish,网页版为 profile_ext)。
  5. 选中该请求,在 Inspectors 面板查看完整的 URL、Header、Body 以及返回的 JSON。

用 Requests 复现抓包请求

抓到请求后,把其中的 URL、Header、Cookie、参数复制到 Requests 代码中即可复现:

python
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 与参数):

python
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 为准。
  • tokenkeypass_ticketappmsg_token 均有有效期,失效后重新抓包获取即可复用同一段代码。
  • 建议控制抓取频率,避免触发风控。

小结

本节完成了公众号爬虫的三个基础技能:

  1. 原理:理解公众号文章通过 HTTP 接口返回,爬虫需要定位接口并模拟请求。
  2. Requests:掌握 GET/POST、请求头、Session、JSON 解析等核心用法。
  3. Fiddler 抓包:学会搭建 PC 端微信抓包环境,抓取并复现公众号接口请求。

下一节将进入正式实战,抓取公众号的历史文章并存储数据。

版本差异(爬虫技术栈 → 当前版本)

本文编写时当前稳定版
requests2.28/2.312.32.x
Scrapy1.x/2.02.11.x(API 稳定)
httpx0.240.28.x
Playwright1.3x1.6x(Python 版)
lxml/BeautifulSoup旧版保持稳定
Python3.8-3.123.14(推荐)

本文讲解的爬虫原理(HTTP、解析、反爬、存储)与核心 API 在最新版本中成立;注意 Python 3.9 及以下已 EOL,新项目使用 3.13/3.14。