App数据的爬取
在网页中,我们可以借助浏览器开发者工具中的Network面板看到网页中产生的所有网络请求和响应内容,然而App怎么办呢?想拦截App中的网络请求,就得用到抓包工具了,例如Charles、Fiddler、mitmproxy等,我们可以通过这些工具拦截App和API通信的请求内容和响应内容,如果能从中找到一定的规律,就可以用程序直接构造请求来模拟API的请求,从而完成数据爬取。
- Charles抓包工具的使用
- Charles是一个网络抓包工具,可以用它抓起App运行过程中产生的所有请求内容和响应内容,这和在浏览器开发者工具的Network面板中看到网页产生的内容是一样的道理。
Charles、Fiddler等都是非常强大的HTTP抓包软件,功能基本类似,下面以Charles作为移动端抓包工具分析App的数据包。
目标
以一个电影示例App为例,利用Charles抓取这个App在运行过程中产生的网络数据包,然后查看具体的请求内容和响应内容。同时使用Python改写抓取到的数据包中的请求,继而爬取App数据。
准备工作
Charles运行在一个电脑上,运行的时候会在该电脑的8888端口开启一个代理服务,首先请确保已经正确安装好Charles并开启了代理服务。本人是mac系统下的Charles试用版。然后再准备一部Android手机或模拟器(系统版本最好在7.0以下),并让手机或模拟器的网络和Charles所在电脑的网络处于同一个局域网下(可以让模拟器通过虚拟网络与电脑连接,也可以让手机真机和电脑连接同一个Wi-Fi)。之后设置好Charles代理和Charles CA证书,在Charles中开启SSL监听整个配置过程可以在[小蜜蜂AI网站][https://zglg.work]的GPT问答获取。SSL代理配置一定要开启,而且Location的host和port都设置为*。
抓包原理
设置手机代理为Charles的代理服务地址,这样手机访问互联网的数据包就会先流经Charles,再由Charles转发给真正的服务器;同样,服务器返回的数据包也会先到达Charles,再由Charles转发给手机。整个过程中的Charles相当于中间人,可以捕获所有数据包,就是可以捕获所有请求内容和响应内容。而且,Charles还可以对请求的内容和响应的内容做修改。
实战抓包
打开Charles,运行界面如下图所示:
Charles会一直监听手机产生的数据包,捕获的数据包将显示在界面左侧,随着时间的推移,会捕获越来越多的数据包,左侧列表里的内容也越来越多。
现在打开手机上下载的app1,(安装包下载地址为https://app1.scrape.center/,访问即可下载)。如下图所示:
会发现Charles已经捕获了对应的数据包,其界面类似下图所示:
在app1里不断上拉,Charles会捕获这个过程中产生的所有网络请求,如下图所示:
可以看到,左侧列表中一个链接是https://app1.scrape.center,在app1里上拉的时候它会一直闪动,这就表示当前app1发出的获取电影数据的请求被Charles捕获了。
为了验证这个结论的正确性,点击上述链接下的一个条目,切换到Contents选项卡,查看其详情。此时界面右侧会显示一些JSON是数据,其中有一个results字段,该字段中每一个条目的name值都是一个电影名称,这些名称与手机界面上的内容一一对应。如下图所示:
所以,https://app1.scrape.center对应的接口就是获取电影数据的接口。
分析
分析捕获的请求内容和响应内容的详细信息,首先回到Overview选项卡,界面右侧的上方显示了请求URL、响应状态码Response Code和请求方法Method等信息,如下图所示,这些内容和在网页中用浏览器开发者工具捕获的内容是类似的。
接下来点击Contents选项卡,查看请求内容和响应内容的详情,界面如下图所示。上半部分显示的是请求的信息,下半部分显示的是响应的信息。切换到Headers选项卡即可看到请求头,切换到JSON Text选项卡即可看到响应体,并且响应体的内容已经被格式化。
由于这个请求是GET请求,因此还需要关心GET的参数信息,切换到Query String选项卡即可查看,如下图所示:
对于其他App,同样可以使用这样的分析方式。如果能直接分析出请求URL和参数的规律,就可以直接模拟发出请求实现数据的批量抓取。
重发
Charles还有一个强大功能,是可以对捕获的请求内容加以修改并把修改后的请求发送出去。点击界面右侧上方的修改按钮,左侧列表就会出现一个以编辑图标为开头的接口,代表我们正在修改此接口对应的请求,如下图所示:
可以修改请求参数中的某个字段,例如这里将offset字段值由0修改为10,如下图所示,然后点击界面下方的Execute按钮即可发送修改后的请求。
可以发现左侧列表出现了对应的请求结果,点击Contents选项卡,查看响应内容,这次返回的是第2个列表页中的电影信息,如下图所示:
有了重发功能,就可以方便的使用Charles做调试了,可以通过修改参数、接口等测试不同请求的响应状态,从而知道哪些参数必要和哪些不必要了,以及参数分别由什么规律,最后抽象出一个最简单的接口供模拟使用。
修改响应内容
除了修改请求内容,Charles还可以修改响应内容,例如将响应内容修改为本地或远程的某个文件,这样就可以实现数据的修改和伪造了。
如何实现呢?右击任意一个请求,可以看到出现的菜单中有Map Remote和Map Local这两个选项,通过这两个选析就可以将响应内容修改为远程或本地文件,如下图所示:
以生成本地文件为例,怎么实现呢?可以先把当前的响应内容,也就是JSON Text的内容复制下来,保存成本地文件,文件名为data.json,如下图所示:
然后修改其中的字段值,例如将第11个条目的name修改为“V字仇杀队VVV“,并保存修改,如下图所示:
再在Map Local的配置中,选定data.json文件的保存路径,如下图所示:
可以发现,第11个电影的名称变成了“V字仇杀队VVV",成功修改了响应的内容。
可以发现,第11个电影的名称变成了“V字仇杀队VVV",成功修改了响应的内容。原理都是修改了HTTP响应的内容,之前的“重发”和这个修改内容的过程可以称为中间人攻击,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
from requests.packages import urllib3
urllib3.disable_warnings()
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, verify=False).json()
print('data', data)
运行结果如下:
data {
'count': 102, 'results': [{
'id': 1, 'name': '霸王别姬', 'alias': 'Farewell My Concubine', 'cover': 'https://p0.meituan.net/movie/ce4da3e03e655b5b88ed31b5cd7896cf62472.jpg@464w_644h_1e_1c', 'categories': ['剧情', '爱情'], 'published_at': '1993-07-26', 'minute': 171, 'score': 9.5, 'regions': ['中国内地', '中国香港'], 'drama': '影片借一出《霸王别姬》的京戏,牵扯出三个人之间一段随时代风云变幻的爱恨情仇。段小楼(张丰毅 饰)与程蝶衣(张国荣 饰)是一对打小一起长大的师兄弟,两人一个演生,一个饰旦,一向配合天衣无缝,尤其一出《霸王别姬》,更是誉满京城,为此,两人约定合演一辈子《霸王别姬》。但两人对戏剧与人生关系的理解有本质不同,段小楼深知戏非人生,程蝶衣则是人戏不分。段小楼在认为该成家立业之时迎娶了名妓菊仙(巩俐 饰),致使程蝶衣认定菊仙是可耻的第三者,使段小楼做了叛徒,自此,三人围绕一出《霸王别姬》生出的爱恨情仇战开始随着时代风云的变迁不断升级,终酿成悲剧。'}, {
'id': 2, 'name': '这个杀手不太冷', 'alias': 'Léon', 'cover': 'https://p1.meituan.net/movie/6bea9af4524dfbd0b668eaa7e187c3df767253.jpg@464w_644h_1e_1c', 'categories': ['剧情', '动作', '犯罪'], 'published_at': '1994-09-14', 'minute': 110, 'score': 9.5, 'regions': ['法国'], 'drama': '里昂(让·雷诺 饰)是名孤独的职业杀手,受人雇佣。一天,邻居家小姑娘马蒂尔德(纳塔丽·波特曼 饰)敲开他的房门,要求在他那里暂避杀身之祸。原来邻居家的主人是警方缉毒组的眼线,只因了一小包毒品而遭恶警(加里·奥德曼 饰)杀害全家的惩罚。马蒂尔德 得到里昂的留救,幸免于难,并留在里昂那里。里昂教小女孩使枪,她教里昂法文,两人关系日趋亲密,相处融洽。 女孩想着去报仇,反倒被抓,里昂及时赶到,将女孩救回。混杂着哀怨情仇的正邪之战渐次升级,更大的冲突在所难免……'}, {
'id': 3, 'name': '肖申克的救赎', 'alias': 'The Shawshank Redemption', 'cover': 'https://p0.meituan.net/movie/283292171619cdfd5b240c8fd093f1eb255670.jpg@464w_644h_1e_1c', 'categories': ['剧情', '犯罪'], 'published_at': '1994-09-10', 'minute': 142, 'score': 9.5, 'regions': ['美国'], 'drama': '20世纪40年代末,小有成就的青年银行家安迪(蒂姆·罗宾斯 饰)因涉嫌杀害妻子及她的情人而锒铛入狱。在这座名为肖申克的监狱内,希望似乎虚无缥缈,终身监禁的惩罚无疑注定了安迪接下来灰暗绝望的人生。未过多久,安迪尝试接近囚犯中颇有声望的瑞德(摩根·弗里曼 饰),
....
....