大师兄的Python学习笔记(二十六): 爬虫(七)
大师兄的Python学习笔记(二十八): 爬虫(九)
九、爬取APP
- 在没有网页端的情况下,可以通过爬取App获取数据。
- APP的反爬虫措施没有那么强,且数据通常是Json格式,所以爬起来可能比web端更简单。
- 常用抓包软件包括:WireShark、Fiddler、Charles、mitmproxy、AnyProxy...
- 可以使用Appium对APP进行自动化控制。
9.1 关于Charles
- Charles是一种网络抓包工具,可以获取App运行过程中发生的所有网络请求和相应内容。
- 可以作为主要的移动端抓包工具,用于抓包分析。
9.1.1 安装Charles
第一步:下载Charles
官网点此处下载安装30天试用版。
第二步:安装PC端Https证书
第三步:安装手机端Https证书
- 首先将电脑和手机接入同一个局域网中。
PC端设置代理并开启。
手机端接入PC端代理。
PC端同意接入。
- 手机端访问http://www.charlesproxy.com/getssl下载证书。
- 下载后在手机端安装证书: 加密和凭据->从存储设备安装
第四步:配置SSL监听
9.1.2 Charles抓包
-
首先确保http和https监听都已经开启。
- 可以考虑将Proxy->Windows Proxy关掉,以便观察手机端数据。
-
用手机打开京东app,并随便打开一件商品。
-
观察PC端Charles抓取到的数据,包括表单和Json格式的数据都已经抓到了。
9.2 关于mitmproxy
- mitmproxy是与Charles类似的抓包程序,但是控制台形式。
- mitmproxy有两个关联组件,分别是mitmdump和mitmweb。
- mitmdump是命令行接口,可以用来对接Python。
- mitmweb是web程序。
9.2.1 安装mitmproxy
- 安装mitmproxy非常简单,只需要使用
pip install mitmproxy
就可以安装mitmproxy、mitmdump和mitmweb。
9.2.2 获取https证书
- 与charles一样,如果想截取https请求,则需要设置证书。
- 谷歌在安卓7.0修改了安全策略,用户添加的CA证书不能再用于安全连接,苹果手机可以正常爬取。
第一步:使用
mitmdump
指令启动mitmdump并生成证书。
第二步: 找到并双击认证mitmproxy-ca-cert.p12证书文件。
第三步: 将证书文件mitmproxy-ca-cert.pem发送到手机端并验证。
9.2.3 手机端配置代理
-
在局域网配置->代理中配置mitmproxy主机的ip地址和port。
9.2.4 使用mitmproxy抓取数据
-
手机端完成代理配置后,就可以启动mitmproxy服务了
-
测试访问页面。
-
如果你用的是windows,也可以使用mitmweb使用网页版抓取数据。
9.2.5 使用mitmdump对接Python
- mitmdump是mitmproxy的命令行对接口,同时也可以对接Python处理请求,这是mitmproxy相比charles的优势。
- 可以添加参数,如
mitmdump -s script.py
使用Python脚本处理截获的数据。 - 此外,在控制台使用
mitmdump -h
可以查看所有参数,其中比较常用的有:
-p port
: 改变端口
-s script.py
: 使用脚本处理截获数据
-w outfile
: 将截获数据保存到文件
- 在Python脚本端,可以使用mitmproxy包处理截获的数据,
mitmproxy.http.HTTPFlow
常用接口如下:
接口 | 作用 |
---|---|
flow.request.headers | 获取所有头信息,包含Host、User-Agent、Content-type等字段 |
flow.request.pretty_url | 完整的请求地址,包含域名及请求参数,但是不包含放在body里面的请求参数 |
flow.request.host | 域名 |
flow.request.method | 请求方式。POST、GET等 |
flow.request.scheme | 什么请求 ,如https |
flow.request.path | 请求的路径,url除域名之外的内容 |
flow.request.get_text() | 请求中body内容,有一些http会把请求参数放在body里面,那么可通过此方法获取,返回字典类型 |
flow.request.query | MultiDictView类型的数据,url直接带的键值参数 |
flow.request.get_content() | bytes,结果如flow.request.get_text() |
flow.request.raw_content | bytes,结果如flow.request.get_content() |
flow.request.urlencoded_form | MultiDictView,content-type:application/x-www-form-urlencoded时的请求参数,不包含url直接带的键值参数 |
flow.request.multipart_form | MultiDictView,content-type:multipart/form-data时的请求参数,不包含url直接带的键值参数 |
flow.response.status_code | 返回状态码 |
flow.response.text | 返回内容,已解码 |
flow.response.content | 返回内容,二进制 |
flow.response.setText() | 修改返回内容,不需要转码 |
- 示例:
>>>from mitmproxy import http
>>>def request(flow):
>>> if flow.request.pretty_url == "http://httpbin.org/get":
>>> flow.response = http.HTTPResponse.make(
>>> 200,
>>> b'Hello World!',
>>> {"Content-Type":"text/html"}
>>> )
9.3 关于Appium
- Appium是一个跨平台移动端自动化测试工具,可以看成是Andriod或IOS端的Selenium。
- 能够在模拟App内部的各种操作,比如点击、滑动、输入等。
9.3.1 安装Appium
-
点击此处下载Appium。
如果需要用安卓手机抓取,则点击此处下载Android Studio。
-
安装Andriod Studio后继续安装Android SDK。
-
配置Android SDK环境变量。
如果使用IOS爬取数据,则需要在mac电脑上执行
xcode-select --install
配置环境。
9.3.2 启动Appium
第一步:打开Appium界面,默认端口为4723。
第二步:配置ANDROID_NAME并点击Start Server启动服务器。
第三步:将手机连接数据线,并打开USB调试功能,通过adb指令检查设备是否匹配成功。
第四步:点击Appium界面的Start Inspector Session按键。
第五步:找到appPackage和appActivity。
- 在cmd使用
adb logcat
指令
- 手机端打开app
-
查看log.txt
第六步:配置Desired Capablilities中的platformName(平台名)、deviceName(设备名)、appPackage(程序包名)和appActivity(入口Activity名)
第七步:点击Start Session按钮
-
如果一切顺利,不仅手机进入启动界面,同时调试窗口会显示页面源码。
-
不仅如此,还可以对元素进行操作,比如点击、输入、拖拽等。
9.3.3 用Python驱动Appium
- 以豆瓣app为例。
- 首先使用
pip install appium-python-client
安装appium包。 - 确保appium server处于开启状态。
>>>from appium import webdriver
>>>from selenium.webdriver.common.by import By
>>>from selenium.webdriver.support.ui import WebDriverWait
>>>from selenium.webdriver.support import expected_conditions as EC
>>>server = 'http://localhost:4723/wd/hub' # 服务器地址
>>>desired_caps = {
>>> # 配置desired参数
>>> "platformName": "Android",
>>> "deviceName": "HUAWEI_mate30_pro",
>>> "appPackage": "com.douban.frodo",
>>> "appActivity": ".activity.SplashActivity"
>>>}
>>>driver = webdriver.Remote(server,desired_caps) # 启动APP
>>>wait = WebDriverWait(driver,30)
>>>next = wait.until(EC.presence_of_all_elements_located((By.ID,'com.douban.frodo:id/next')))[0]
>>>next.click() # 点击下一步
>>>prim_confirm = wait.until(EC.presence_of_all_elements_located((By.ID,'android:id/button1')))[0]
>>>prim_confirm.click() # 确认给予权限
>>>cancel_login = wait.until(EC.presence_of_all_elements_located((By.ID,'com.douban.frodo:id/close')))[0]
>>>cancel_login.click() # 为了方便演示,这里就先不登录了
>>># 切换tap刷新页面
>>>tap_2 = wait.until(EC.presence_of_all_elements_located((By.ID,'com.douban.frodo:id/icon')))[1]
>>>tap_2.click()
>>>tap_1 = wait.until(EC.presence_of_all_elements_located((By.ID,'com.douban.frodo:id/icon')))[0]
>>>tap_1.click()
>>># 获取推荐内容
>>>contents = wait.until(EC.presence_of_all_elements_located((By.ID,'com.douban.frodo:id/status_text')))
>>>for content in contents:
>>> print(content.get_attribute("text"))
现在都懒得攒着,随手扔了
参考资料
- https://blog.csdn.net/u010138758/article/details/80152151 J-Ombudsman
- https://www.cnblogs.com/zhuluqing/p/8832205.html moisiet
- https://www.runoob.com 菜鸟教程
- http://www.tulingxueyuan.com/ 北京图灵学院
- http://www.imooc.com/article/19184?block_id=tuijian_wz#child_5_1 两点水
- https://blog.csdn.net/weixin_44213550/article/details/91346411 python老菜鸟
- https://realpython.com/python-string-formatting/ Dan Bader
- https://www.liaoxuefeng.com/ 廖雪峰
- https://blog.csdn.net/Gnewocean/article/details/85319590 新海说
- https://www.cnblogs.com/Nicholas0707/p/9021672.html Nicholas
- https://www.cnblogs.com/dalaoban/p/9331113.html 超天大圣
- https://blog.csdn.net/zhubao124/article/details/81662775 zhubao124
- https://blog.csdn.net/z59d8m6e40/article/details/72871485 z59d8m6e40
- https://www.jianshu.com/p/2b04f5eb5785 MR_ChanHwang
- 《Python学习手册》Mark Lutz
- 《Python编程 从入门到实践》Eric Matthes
- 《Python3网络爬虫开发实战》崔庆才
本文作者:大师兄(superkmi)