☰
Fiddler抓包+Python采集移动端数据实战指南
2026/10/14 0:27:13 网站建设 项目流程

1. 抓包这件事,为什么值得花时间啃

做数据采集的人迟早会撞上一堵墙:网页端的数据越来越难拿。接口加密、参数签名、请求头校验、频率限制,一层套一层。很多人第一反应是上自动化浏览器,模拟点击、滚动、等待渲染,结果资源消耗大、速度慢、稳定性还差。我早期也走过这条路,一个列表页翻二十页要跑好几分钟,稍微改个样式整个脚本就崩了。

后来我把思路换了一下:与其在网页端跟反爬机制硬碰硬,不如去看看移动端。移动应用的网络请求往往比网页端“诚实”得多——它要跟服务端通信,就得发请求,而很多应用的请求参数并没有网页端那么复杂。问题在于,手机上的流量你看不见。这时候就需要一个中间人,把手机发出的请求和服务器返回的响应都截下来看个清楚。这个中间人就是抓包工具。

这篇文章要聊的,就是怎么用 Fiddler 这个老牌抓包工具,把移动端应用的数据接口摸清楚,然后用 Python 把数据采集流程跑通。整套流程走下来,你能拿到干净的 JSON 数据,不用解析 HTML,不用处理渲染,速度还快。适合有一定 Python 基础、想入门移动端数据采集的读者,也适合做过网页采集、想拓展技术边界的同行。

我选 Fiddler 而不是其他工具,理由很实在:它在 Windows 上安装简单,证书配置流程成熟,界面直观,抓到的请求可以直接右键复制成各种语言的代码。对于刚接触抓包的人来说,学习曲线比命令行工具平缓得多。当然它也有局限,后面会讲到。

提醒:抓包技术本身是中性的,但使用它有明确的边界。只采集公开的、非敏感的数据,遵守目标平台的服务条款,控制请求频率,不要对服务器造成压力。这是做这行的基本职业操守。

2. 整体方案设计与工具选型思路

2.1 为什么是“抓包 + Python 请求”而不是“模拟浏览器”

先把这个核心决策讲清楚,因为它决定了后面所有工作的方向。

模拟浏览器方案的本质是:我控制一个真实的浏览器,让它去加载页面、执行 JavaScript、渲染内容,然后我从渲染后的 DOM 里提取数据。这个方案的优点是通用性强,什么页面都能对付。缺点也很明显:慢、重、脆。一个浏览器实例占几百兆内存,加载一个页面要等网络、等渲染、等异步请求,页面结构一变选择器就失效。

抓包方案的本质是:我直接找到应用跟服务器通信的那个接口,绕过界面,直接跟接口对话。接口返回的是结构化数据,通常是 JSON,字段清晰,解析简单。速度上,一个请求几十毫秒就回来了,比渲染页面快一个数量级。稳定性上,只要接口协议不变,界面怎么改都不影响我。

那为什么还需要抓包这一步?因为接口的地址、参数、请求头这些信息,你光看应用界面是看不出来的。抓包就是把这个“暗箱”打开,让你看清楚数据是怎么流动的。

2.2 Fiddler 的工作原理:中间人机制

Fiddler 的核心是一个代理服务器。它在你的电脑上启动一个 HTTP 代理,监听某个端口(默认 8888)。当手机把代理指向这台电脑后,手机发出的所有网络请求都会先经过 Fiddler,Fiddler 记录下来,再转发给真正的服务器;服务器返回的响应也是先到 Fiddler,再回到手机。

这里有个关键问题:现在的应用基本都用 HTTPS,数据是加密的。Fiddler 要能看懂加密内容,就必须做一件事——中间人解密。它会给手机出示一个自己签发的证书,手机如果信任这个证书,就会把加密数据发给 Fiddler,Fiddler 解密后再用真正的服务器证书重新加密转发。这就是为什么抓 HTTPS 必须安装并信任 Fiddler 的根证书。

理解了这个机制,后面配置证书时遇到的很多问题就都能想明白了。比如手机提示“证书不受信任”,本质就是手机不认 Fiddler 这个中间人。

2.3 工具清单与各自角色

整套方案涉及的工具不多,但每个都有明确分工:

工具角色关键作用
Fiddler抓包代理截获并解密移动端请求,定位目标接口
手机/模拟器请求发起端运行目标应用,产生真实网络流量
Python requests请求复现用代码模拟接口请求,批量采集数据
JSON 解析库数据处理从响应中提取结构化字段

手机端我建议用安卓模拟器,原因有两个:一是模拟器和 Fiddler 在同一台电脑上,网络配置简单,不用折腾局域网;二是模拟器可以随时重置,装证书、卸证书都方便,不污染真机环境。当然用真机也行,只是要确保手机和电脑在同一个局域网下。

2.4 方案的优势与边界

这套方案的优势前面说了:快、稳、数据干净。但它不是万能的,有几个边界要提前认清。

第一,它依赖接口协议不变。如果目标应用某天改了接口地址、加了签名校验、换了加密方式,你的脚本就得跟着改。这不是方案的问题,是数据采集的常态。

第二,它需要你能抓到包。有些应用做了证书校验(SSL Pinning),不信任用户安装的证书,这种情况下 Fiddler 抓到的会是乱码或者直接抓不到。应对方法有,但超出了入门范围,后面会简单提一下思路。

第三,它要求你理解 HTTP 协议。请求方法、请求头、请求体、状态码、Cookie,这些概念得清楚,否则抓到了包也看不懂。

3. 环境搭建与抓包配置的完整实操

3.1 Fiddler 安装与基础设置

Fiddler 的安装没什么好说的,官网下载安装包,一路下一步。装完之后第一次打开,界面可能有点劝退——密密麻麻的会话列表,各种图标。别慌,常用的就那几个区域。

先做几项基础设置,这些设置直接影响后面能不能顺利抓到 HTTPS:

打开 Tools → Options → HTTPS,勾选 Capture HTTPS CONNECTs 和 Decrypt HTTPS traffic。第一次勾选时会提示安装根证书,点“是”。这个证书就是 Fiddler 用来做中间人的凭证。

然后到 Connections 标签页,确认 Allow remote computers to connect 是勾选状态。这个选项允许其他设备(比如手机)把 Fiddler 当代理。端口默认 8888,记下来,手机配置时要用。

设置完记得重启 Fiddler,让配置生效。

注意:如果安装证书时弹出安全警告,选择“是”继续。这个证书只用于本机抓包,不安装的话 HTTPS 流量全是加密的,看不到内容。

3.2 手机端代理与证书配置

这一步是新手最容易卡住的地方,我把流程拆细一点。

先确认电脑的局域网 IP。在命令行里输入ipconfig,找到当前网卡的 IPv4 地址,通常是 192.168.x.x 这种格式。记下来。

然后打开手机的 WiFi 设置,找到当前连接的网络,把代理模式改成“手动”,主机名填电脑的 IP,端口填 8888。保存。

这时候手机的网络请求就会经过 Fiddler 了。但 HTTPS 还是解不开,因为手机不信任 Fiddler 的证书。接下来装证书。

在手机浏览器里访问http://电脑IP:8888,Fiddler 会返回一个页面,上面有个链接可以下载证书。下载下来之后,到手机的设置里找到“安全”或“加密与凭据”,选择“从存储设备安装证书”,找到刚下载的文件安装。

安卓 7.0 以后有个坑:用户安装的证书默认不被应用信任,只有系统级证书才被信任。这意味着即使你装了 Fiddler 证书,某些应用还是抓不到。解决办法有两个:一是用安卓 7.0 以下的模拟器,二是把证书装到系统分区(需要 root)。入门阶段我建议先用低版本模拟器,省去这些麻烦。

3.3 验证抓包是否成功

配置完之后,打开手机上的浏览器,随便访问一个网站。回到 Fiddler,看左侧会话列表有没有新的请求出现。如果有,说明代理配置成功了。

再验证 HTTPS 解密。找一个 HTTPS 网站访问,看 Fiddler 里对应的会话,点开 Inspectors → TextView,如果能看到明文内容,说明证书也配置对了。如果看到的是乱码,说明解密没成功,回去检查证书安装步骤。

这两步验证通过,抓包环境就算搭好了。接下来就是找目标接口。

3.4 定位目标接口的实操技巧

打开目标应用,在 Fiddler 里清空会话列表(快捷键 Ctrl+X),然后在应用里做一次你想采集的操作,比如刷新列表、下拉加载。操作完回到 Fiddler,会话列表里就会多出一批请求。

怎么从这一堆请求里找到你要的那个?我的经验是按这几个特征筛:

看 Host,通常是应用的域名或者 CDN 域名。看 URL 路径,一般会包含 list、feed、recommend、content 这类关键词。看响应类型,点开 Inspectors → TextView,如果返回的是结构化的 JSON,而且里面有你要的字段(比如标题、作者、时间),那基本就是它了。

找到之后,右键这个请求,选择 Copy → Copy as cURL,或者直接看 Inspectors → Headers 里的请求信息。把 URL、请求方法、请求头、请求参数都记下来,这些就是后面写 Python 代码要用的素材。

实操心得:目标接口往往不止一个。列表接口负责返回内容列表,详情接口负责返回单条内容的完整信息,评论接口负责返回评论。采集完整数据通常需要组合多个接口。先把列表接口跑通,再逐步扩展。

4. 从抓包结果到 Python 采集脚本

4.1 请求信息的解读与提取

抓到接口之后,别急着写代码,先把请求信息吃透。一个典型的移动端接口请求包含这几部分:

请求 URL,比如https://api.example.com/feed/list?page=1&size=20。请求方法,GET 或 POST。请求头,里面有几个关键字段:User-Agent 标识客户端类型,Referer 标识来源,Cookie 或 Token 用于身份验证,还有一些自定义头用于签名或版本控制。请求体,POST 请求才会有,通常是 JSON 或表单数据。

这里要特别关注身份验证相关的字段。移动端接口常见的验证方式有几种:一种是 Token 放在请求头里,一种是签名参数放在 URL 或请求体里,还有一种是 Cookie。抓包的时候这些都能看到,写代码时原样带上就行。

但要注意,Token 和签名往往有时效性。Token 可能几小时或几天过期,签名可能跟时间戳绑定。这意味着你的脚本不能一劳永逸,需要定期更新这些参数。入门阶段可以先手动更新,跑通流程后再考虑自动化。

4.2 用 requests 复现请求

Python 的 requests 库是复现请求的最佳选择,语法简洁,功能完整。下面是一个基本的请求复现框架:

import requests import json import time headers = { "User-Agent": "抓包时看到的UA", "Referer": "抓包时看到的Referer", "Cookie": "抓包时看到的Cookie", "Authorization": "抓包时看到的Token", } params = { "page": 1, "size": 20, } url = "https://api.example.com/feed/list" response = requests.get(url, headers=headers, params=params, timeout=10) data = response.json() print(json.dumps(data, ensure_ascii=False, indent=2))

这段代码的关键在于 headers 和 params 要跟抓包结果一致。少一个字段,服务器可能就返回错误。我建议第一次复现时,把抓包看到的所有请求头都带上,跑通之后再逐个删减,看哪些是必需的。这样既能保证成功,又能精简代码。

4.3 响应数据的解析与字段提取

接口返回的 JSON 结构通常是有规律的。以内容列表为例,典型结构是这样的:

{ "code": 0, "message": "success", "data": { "list": [ { "id": "123456", "title": "内容标题", "author": "作者名", "publish_time": 1699999999, "content": "内容正文" } ], "has_more": true, "next_page": 2 } }

解析的时候,先判断 code 是否为成功状态,再从 data.list 里遍历每一条,提取需要的字段。分页信息通常在 has_more 和 next_page 里,用来控制翻页。

if data.get("code") == 0: items = data["data"]["list"] for item in items: record = { "id": item.get("id"), "title": item.get("title"), "author": item.get("author"), "publish_time": item.get("publish_time"), } print(record)

字段提取有个原则:用 get 方法而不是直接索引。接口字段可能缺失或改名,用 get 能避免 KeyError 导致脚本崩溃。

4.4 翻页逻辑与数据存储

翻页是采集的核心环节。移动端接口的翻页方式主要有三种:页码翻页(page 递增)、游标翻页(用上一页返回的 cursor 或 next_page)、时间戳翻页(用上一页最后一条的时间)。

页码翻页最简单,循环递增 page 就行。游标翻页需要从响应里取下一页的游标值。时间戳翻页需要记录上一页最后一条的时间,作为下一页的请求参数。

不管哪种方式,都要设置终止条件。常见的有:has_more 为 false、返回列表为空、达到预设的最大页数。没有终止条件的循环是灾难,会一直请求下去。

数据存储方面,入门阶段用 CSV 或 JSON 文件就够了。数据量大或者需要查询分析时,再上数据库。存 CSV 的代码很简单:

import csv with open("data.csv", "a", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=["id", "title", "author", "publish_time"]) writer.writeheader() # 只在第一次写 writer.writerows(all_records)

注意编码用 utf-8-sig,这样 Excel 打开不会乱码。这个细节很多人踩过坑。

4.5 请求频率控制与异常处理

采集脚本跑起来之后,最怕两件事:一是被服务器封,二是中途崩溃。

防封的核心是控制频率。我的经验是每次请求之间随机 sleep 1 到 3 秒,模拟人的操作节奏。固定间隔容易被识别,随机间隔更自然。如果发现响应变慢或者返回错误码,立即加大间隔或者暂停。

异常处理要覆盖网络超时、连接错误、JSON 解析失败、字段缺失这几种情况。用 try-except 包住每个请求,出错时记录日志并跳过,不要让整个脚本挂掉。

import random for page in range(1, max_page + 1): try: response = requests.get(url, headers=headers, params={"page": page}, timeout=10) data = response.json() # 处理数据 except requests.exceptions.Timeout: print(f"第 {page} 页请求超时,跳过") except requests.exceptions.RequestException as e: print(f"第 {page} 页请求失败:{e}") except json.JSONDecodeError: print(f"第 {page} 页响应不是合法 JSON") time.sleep(random.uniform(1, 3))

这段代码看起来简单,但能挡住大部分意外情况。跑采集脚本,稳定比快重要。

5. 常见问题排查与避坑经验

5.1 抓包阶段的高频问题

抓包阶段的问题集中在“抓不到”和“看不懂”两类。

抓不到的情况,先检查代理配置。手机和电脑是否在同一网络,代理 IP 和端口是否填对,Fiddler 是否允许远程连接。这些都对的话,看 Fiddler 的会话列表有没有任何请求。如果一个都没有,说明代理没生效,重启 Fiddler 和手机 WiFi 再试。

有请求但 HTTPS 内容是乱码,说明证书没装好或者没被信任。重新下载安装证书,注意安卓 7.0 以上的信任问题。如果目标应用做了证书校验,Fiddler 会显示 CONNECT 请求但内容解不开,这种情况入门阶段建议换个目标练手。

看不懂的情况,通常是请求太多不知道哪个是目标。用过滤功能,在 Fiddler 右下角的 Filter 里设置只显示特定 Host 的请求,能大幅减少干扰。

5.2 脚本复现阶段的典型报错

脚本跑不通,报错信息就是线索。我整理了一个速查表:

报错现象可能原因解决方向
403 Forbidden请求头缺失或 Token 失效补全请求头,更新 Token
401 Unauthorized身份验证失败检查 Cookie 或 Authorization
返回空数据参数错误或接口变更对比抓包参数,确认接口未改
返回 HTML 而非 JSON被重定向或触发验证检查 URL,降低请求频率
连接超时网络问题或 IP 被封检查网络,更换出口,加大间隔
JSON 解析失败响应格式变化打印原始响应排查

这张表覆盖了我遇到过的大部分情况。实际排查时,第一步永远是打印原始响应,看清楚服务器到底返回了什么。很多人一看到报错就改代码,其实应该先看响应内容。

5.3 身份验证参数的时效性处理

Token 和签名过期是采集脚本最常见的“突然失效”原因。表现是昨天还跑得好好的,今天全部返回 401。

处理思路有两种。一种是定期手动更新,适合采集频率不高的场景。把 Token 存在配置文件里,过期了重新抓包替换。另一种是自动刷新,通过分析应用的登录接口或刷新接口,用代码获取新 Token。后者需要额外的抓包分析,复杂度更高。

我的建议是入门阶段先用第一种,把主要精力放在数据采集和存储上。等整个流程稳定了,再考虑自动化 Token 管理。

5.4 几个容易忽略的细节

第一个细节是请求头的顺序。有些服务器会校验请求头的顺序,虽然少见但确实存在。用 requests 时,headers 字典在 Python 3.7 以后是有序的,按抓包看到的顺序写就行。

第二个细节是 URL 编码。参数里有中文或特殊字符时,requests 会自动编码,但有时候编码方式跟应用不一致,导致服务器不认。这种情况手动用 urllib.parse.quote 处理一下。

第三个细节是响应压缩。有些接口返回 gzip 压缩的数据,requests 会自动解压,但如果你手动处理了响应内容,可能拿到的是压缩后的二进制。用 response.text 或 response.json() 让 requests 帮你处理。

第四个细节是并发。单线程采集慢,但多线程容易触发频率限制。折中方案是用线程池控制并发数,比如 3 到 5 个线程,配合每个线程独立的 sleep。这个进阶话题这里不展开,先把单线程跑稳。

6. 采集流程的扩展与长期维护

6.1 从单接口到多接口组合

跑通列表接口之后,你会发现列表返回的字段往往不全。正文、评论、作者详情这些需要调额外的接口。这时候采集流程就从单接口变成多接口组合。

思路是分两步:先采集列表,拿到每条内容的 ID;再根据 ID 逐个请求详情接口,补充完整信息。详情接口的请求频率要控制得更低,因为请求量成倍增加。

代码结构上,把请求逻辑封装成函数,列表采集和详情采集分开,中间用 ID 关联。这样代码清晰,也方便单独调试某个环节。

6.2 数据去重与增量采集

长期采集同一个数据源,去重是必须的。最简单的方法是用内容的唯一 ID 做去重,存数据前先查一下这个 ID 是否已存在。

增量采集的思路是记录上次采集的位置或时间,下次从那里继续。页码翻页可以记录最大页码,游标翻页可以记录最后的游标值,时间戳翻页可以记录最后的时间。把这些状态存到文件或数据库里,脚本启动时读取,就能实现断点续采。

6.3 脚本的稳定性加固

一个能长期跑的采集脚本,需要具备几个特性:出错不崩、断点续采、日志清晰、配置外置。

出错不崩前面讲了,用 try-except 包住每个请求。断点续采靠状态记录。日志用 logging 模块,记录每次请求的结果和异常,方便事后排查。配置外置是把 URL、请求头、Token 这些易变的东西放到单独的配置文件里,改的时候不用动代码。

这些加固措施看起来繁琐,但当你需要连续跑几天采集时,它们能省下大量重新调试的时间。

6.4 合规采集的边界意识

最后聊聊边界。技术能力是一回事,怎么用是另一回事。

采集公开数据用于个人学习研究,跟大规模抓取用于商业用途,性质完全不同。前者通常没问题,后者可能违反平台条款甚至相关法律。我的原则是:只采集公开可见的数据,控制频率不对服务器造成压力,不采集个人隐私信息,不将数据用于商业牟利。

具体到操作上,遵守目标平台的 robots 协议,设置合理的请求间隔,遇到明确的禁止声明就停止。这些不是技术限制,是职业底线。

抓包和接口采集这套技能,本质上是理解网络通信的一种方式。掌握了它,你看待数据流动的视角会不一样。但能力越大,越要知道边界在哪。这是我在这个领域摸爬滚打这些年最深的体会。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询