Charles抓包工具的使用
Charles 是一个网络抓包工具,我们可以用它抓取 App 运行过程中产生的所有请求内容和响应内容,这和在浏览器开发工具的 Network 面板中看到网页产生的内容是一样的道理。
Charles、Fiddler 等都是非常强大的 HTTP 抓包软件,功能基本类似,本节我们选择 Charles 作为主要的移动端抓包工具来分析 App 的数据包,以便之后爬取 App 的数据。
本节目标
本节我们会以一个电影示例 App 为例,利用 Charles 抓取这个 App 在运行过程中产生的网络数据包,然后查看具体的请求内容和响应内容。
同时,我们会使用 Python 改写抓取到的数据包中的请求,继而爬取 App 的数据。
准备工作
Charles 运行在一个电脑上,运行的时候会在该电脑的 8888 端口开启一个代理服务,首先请确保已经正确安装好 Charles 并开启了代理服务。
然后准备一部 Android 手机或模拟器(系统版本最好在 7.0 以下),并让手机或模拟器的网络和 Charles 所在电脑的网络处于同一个局域网下(可以让模拟器通过虚拟网络与电脑连接,也可以让手机真机和电脑连接同一个 Wi-Fi)。
之后设置好 Charles 代理和 CharlesCA 证书,在 Charles 中开启 SSL 监听。整个配置过程可以参考 https://setup.scrape.center/charles。
另外需在手机上安装示例 App,安装包下载地址为 https://appl.scrape.center/ ,访问即可下载。
|
为了方便,本节后续的内容会统一使用 “手机” 指代 “手机真机” 或 “模拟器”。 |
抓包原理
设置手机代理为 Charles 的代理服务的地址,这样手机访问互联网的数据包就会先流经 Charles 再由 Charles 转发给真正的服务器;同样,服务器返回的数据包会先到达 Charles,再由 Charles 转发给手机。整个过程中的 Charles 相当于中间人,可以捕获所有数据包,意味着可以捕获所有请求内容和响应内容。不仅如此,Charles 还可以对请求内容和响应内容做修改。
实战抓包
打开 Charles,初始运行界面如图 12-1 所示。
图 12-1 Charles 的初始运行界面
Charles 会一直监听手机产生的数据包,捕获的数据包将显示在界面左侧,随着时间的推移,会捕获越来越多的数据包,左侧列表里的内容也越来越多。
现在打开手机上下载的 app1,其界面如图 12-2 所示。
会发现 Charles 已经捕获了对应的数据包,其界面类似图 12-3(注意一定要提前设置好 Charles 代理以及 Charles CA 证书,否则没有效果)。
图12-2 app1 的界面 图12-3 打开 app1 后,Charles 的界面
在 app1 里不断上拉,Charles 会捕获这个过程中产生的所有网络请求,图12-4中左侧的列表展示了捕获的数据包。
可以看到,左侧列表中有一个链接是 https://appl.scrape.center ,在 app1 里上拉的时候它会一直闪动,这就表示当前 app1 发出的获取电影数据的请求被 Charles 捕获了。
为了验证这个结论的正确性,点击上述链接下的一个条目,切换到 Contents 选项卡,查看其详情。此时界面右侧会显示一些 JSON 数据,其中有一个 results 字段,该字段中每一个条目里的 name 值都是一个电影的名称,这些名称与图 12-2 中的电影一一对应,如图 12-5 所示。
图12-5 所捕获数据的具体内容
至此可以确定, https://app1.scrape.center 对应的接口就是获取电影数据的接口。这样我们就成功捕获了在上拉刷新过程中产生的请求内容和响应内容。
分析
现在分析一下捕获的请求内容和响应内容的详细信息。首先回到 Overview 选项卡,界面右侧的上方显示了请求 URL、响应状态码 ResponseCode 和请求方法 Method 等信息,如图 12-6 所示,这些内容和在网页中用浏览器开发者工具捕获的内容是类似的。
图12-6 Overview 选项卡下的内容
接下来点击 Contents 选项卡,查看请求内容和响应内容的详情,界面如图 12-7 所示。上半部分显示的是请求的信息,下半部分显示的是响应的信息。切换到 Headers 选项卡即可看到请求头,切换到 JSONText 选项卡即可看到响应体,并且响应体的内容已经被格式化。
图12-7 Contents 选项卡下的内容
由于这个请求是 GET 请求,因此还需要关心 GET 的参数信息,切换到 QueryString 选项卡即可查看,如图 12-8 所示。
图12-8 GET 的参数信息
对于其他 App,同样可以使用本节的分析方式。如果能直接分析出请求 URL 和参数的规律,就可以直接模拟发出请求实现数据的批量抓取。
重发
Charles 还有一个强大功能,是可以对捕获的请求内容加以修改并把修改后的请求发送出去。点击界面右侧上方的修改按钮,左侧列表就会出现一个以编辑图标为开头的接口,代表我们正在修改此接口对应的请求,如图 12-9 所示。
图 12-9 修改捕获的请求
可以修改请求参数中的某个字段,例如这里将 offset 字段的值由 0 修改为 10,如图 12-10 所示,然后点击界面下方的 Execute 按钮即可发送修改后的请求。
图12-10 将 offset 字段的值由0修改为10
可以发现左侧列表出现了对应的请求结果,点击 Contents 选项卡,查看响应内容,这次返回的是第 2 个列表页中的电影信息,如图12-11所示。
图12-11 返回了第 11~20 个电影的信息
有了重发功能,就可以方便地使用 Charles 做调试了,可以通过修改参数、接口等测试不同请求的响应状态,从而知道哪些参数必要和哪些不必要,以及参数分别有什么规律,最后抽象出一个最简单的接口供模拟使用。
修改响应内容
除了修改请求内容,Charles 还可以修改响应内容,例如将响应内容修改为本地或远程的某个文件,这样就可以实现数据的修改和伪造了。
怎么实现呢?右击任意一个请求,可以看到出现的菜单中有 MapRemote 和 MapLocal 这两个选项,通过这两个选项就可以将响应内容修改为远程或本地的文件,如图12-12所示。
以生成本地文件为例,怎么实现呢?可以先把当前的响应内容,也就是 JSONText 的内容复制下来,保存成本地文件,文件名是 data.json,如图 12-13 所示。
图12-12 MapRemote 和 MapLocal 选项 图12-13 保存当前的响应内容
然后修改其中的字段值,例如将第一个条目的 name 值修改为 “霸王别姬2",并保存修改,如图12-14 所示。
图12-14 修改响应内容中的字段值
再在 MapLocal 的配置中,选定 data.json 文件的保存路径,如图 12-15 所示。
这样,我们就把 app1 的第一个请求一一加载列表页成功修改成本地文件 data.json 中的内容了。接下来重新启动 app1,界面如图 12-16 所示。
图12-15 配置 MapLocal 图12-16 重启 app1 后的界面
可以发现,第一个电影的名称变成了 “霸王别姬2”,我们成功修改了响应内容。
这和 11.11 节内容的原理其实都是修改了 HTTP 响应的内容。在 11.11 节中,我们使用 Playwright 修改了网页中要加载的一些数据文件,将它们映射为本地的文件,整个过程是依据 Playwright 中设置的规则完成的,此处是借助 Charles 完成。
可以把前面所讲的 “重发” 和这个过程称为中间人攻击,Charles 就相当于中间人,它可以拦截请求内容和响应内容,并对这些内容进行修改,而手机端完全无感。
模拟爬取
现在我们已经成功完成了抓包操作记,app1 发出的所有请求三自了然,请求 URL 就是 https://app1.scrape.center/api/movie/ ,后面跟着两个请求参数 offset 和 limit。显然,offset 就是偏移量,limit 就是一次的返回结果中包含的条目数量。例如 offset 为 20,limit 为 10,代表返回第 21~30 条电影的信息。另外,通过观察可以发现一共有 100 个电影,因此 offset 取 0、10、20、…、90,limit 则恒为 10。
接下来我们用 Python 简单模拟一下请求,这里写法有一些从简,代码如下:
import requests
BASE_URL = 'https://app1.scrape.center/api/movie?offset={offset}&limit=10'
for i in range(0, 10):
offset = i * 10
url = BASE_URL.format(offset = offset)
data = requests.get(url).json()
print('data', data)
运行结果如下:
可以看到,我们轻松模拟了每个请求,并爬取了服务器的响应内容。
由于 app1 的接口没有任何加密措施,因此我们仅仅靠抓包以及观察数据包的规律就轻松模拟了 app1 的请求。