最近对某个app进行分析,打算全自动的生成一些截屏来为自己视频的生成准备素材,发现只能抓到初始界面的几个remote link的请求,其它抓取不到,你遇到过类似的问题吗?
为了解决这个问题,于是一顿操作猛如虎,于是有了这篇文章。本文主要把全过程记录一下,供大家参考。
因为我是用模拟器,你就知道市面上模拟器都是针对安卓的,所以,你也就知道了,你操作的也都是安装在模拟器中的安卓应用。我的目的就是想通过python可以直接操作模拟器中的应用来完成相应的操作,如果你用过selenium、puppeteer做过模拟请求或自动化测试,你大概应该知道我在讲什么。
adb
对它们进行控制因为模拟器就相当于一个安卓的虚拟机,如果你用过docker的话,adb
就相当于一个docker-compose
工具,可以管理容器,如果你用过k8s
,那么adb
相当于kube-apiserver
,它可以对所有容器进行交互管理。模拟器里安装个啥应用,模拟器里某应用由哪些Activity
构成,这些都是后续对应用进行模拟操作的基础。 这里把安装过程大致说一下:
compiler
时都可以指定版本进行下载。区别在于前者你可以自己指定位置,而后者你可能不知道安装到到哪里了。然后在根目录下.bash_profile
或.zshrc
中声明。 export JAVA_HOME=~/Library/Java/JavaVirtualMachines/openjdk-17.0.2/Contents/Home
android-studio
编辑器,指定了jdk位置之后,它会直接把andriod-sdk
下到~/Library/Android/sdk
目录下的,声明位置同上。
//根目录下`.bash_profile`或`.zshrc`中声明
export ANDROID_HOME=~/Library/Android/sdk
export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
特别提示: 如果你用brew安装andriod-sdk,一定要注意同时安装andriod-platform-tools,但是用brew命令进行的安装,这两个东西又不在sdk的根目录下,与网上所有教程陈述的只要配置了ANDRIOD_HOME,再把它下辖的tools和platform-toos指定到环境变量中就可用了是不相符的,所以我还是建立用我说的使用andriod-studio方式进行安装。而且这样安装的andriod-sdk,有些是下到了Cellar
目录下,有些是下到了Caskhome
目录下,总之让人非常糊涂。
当然如果你一定想通过这种方式,提供几个命令希望对你有帮助。
brew install --cask andriod-sdk
brew install --cask android-platform-tools
brew list android-sdk //查看具体的安装目录
最终如果你用命令adb
在命令行窗口敲击,有使用命令提示,就说明安装成功了,如果你的模拟器已经运行起来了,可以用adb devices
查看有哪些在运行的安卓服务
如果做爬虫工具做多了,你可能遇到过各种各样的问题。我举几个例子,比如说我抓包过的某国外网站,网站其实架构挺简单的,用的drupal
,但是它主体的内容,必须要你人工往下拉窗体,才能把内容后半部分加载出来,像这种我用scrapy
单纯靠dom
节点分析xpath
或者re
做匹配就很难抓取到完整内容,这个时候,就只能靠模拟人为操作或者headless浏览器了。而在手机抓包这种模拟操作就不是可选项了,而成了必选项,就是你必须模拟人为操作,才能产生和该手机后端服务的交互,才可能刷到你要的数据,所以,对于交互过程发生了哪些变化,产生了哪些数据就成了必做的功课,抓包的意义也就体现出来了。
抓包工具分为几类,像我们电脑端常用的Charles
、Fiddler
是属于正向代理的工具。如果你对网络请求七层模型有了解的话,你知道这些发生在“会话层、表示层、应用层(TCP/IP五层模型里面)这三层统称为应用层
”应用层,而应用层的代理是很容易被绕过的,如果再往底层探一探,能拿到的数据就更多,比如说下探到传输层,通常意义我们安卓上使用的Trony
,ios
上使用的小火箭shadownsockets
其实都在充当vpn
作用再这层。再往下探比如说wireshack
已经可以操作网卡了,只要数据有经过指定网卡,都会被抓取。而像nginx
这样的反向代理工具,它实际是代理的服务层,起到了类似vpn
的效果。就是不让请求端知道谁在提供服务,它承接所有请求,再把请求转发给具体应用进行处理,你如果作为客户端,后面实际提供的服务对你来说就相当于黑盒。而对于客户端代理Charles、Fiddler
很多请求抓不到,就是这个原因,有些应用,对于代理它做请求直接就是屏蔽的,所以对于这种你完完全全抓住个寂寞。对于这种情况,我们就要想办法,能不能让手机等应用所有input/output流量都有个统一卡口,这样你再监控这个卡口,应用上所有交互就都能被侦测到了,有没有这样一个工具呢?可爱的Trony
它出现了,没错,它就是这样一个工具。要强调一下,如果应用本身就没对客户端的代理屏蔽,那你就没必要上Trony
了,具体部署开始。
网络七层模型
Charles
,这个网上各种教程,一看便懂Charles+Trony
,这里强调一下Trony
在模拟器安装好之后,如果原来你在wifi
里开启了手动代理,将请求转发到本机电脑了,这里就要把这里手动代理
给关闭,因为现在你用Trony
接管你所有流量,所有东西都要在Trony
中设置。具体配置网上也能找到,我详述。这里关键的一点就是第二步工具配置好了以后,流量被抓到显示在哪里。Charles
的默认端口是8888
,你用ifconfig
命令查看一下en0
中inet
的ip值,就是你本机地址,这样手机应用的流量都经过Charles
代理完成交互,你在Charles
上能看到这些请求,这也就是抓包的原理。而Charles+Trony
原理也是一样,最终流量都经过Charles
,所以会被抓到,你就能查看到。区别只在于Trony
帮你解决了有些手机应用不允许用代理,或者其它对你屏蔽请求的状况下,它强制所有流量都走它,它又把请求代理给你的Charles
,至此对你不可见的流量你也能看见了。总之,最终请求都是被抓到了Charles
里面。
我们上面折腾那么多,抓到app的各种请求,总有个最终目的。如果你是测试人员,这个时候,你可以总结测试用例了,比如说这次准备上线三个应用Activity
,每个界面有几个接口,第一屏接口对嘛,数据对吗?这是可以人肉测的内容。如果你是自动化测试人员,你就可以写脚本了,文档定义出的接口返回结构,charles抓包返回结构,遍历打印看结构一不一致啥的,至于数据准不准可能就得要算一算或者看产品文档了。因为我是打算模拟操作,然后截屏,所以我需要有个可以支撑我搞自动化的工具,它就是Appium
,它还有个客户端,安装客户端的好处就是它能帮你把用自动化工具和安卓模拟器里的应用做的交互的过程给打印出来,这样也方便你调试。
pip install Appium-Python-Client Selenium
命令安装,之后用from appium import webdriver
引入就可以耍戏安卓应用了举个栗子,我打开应用的首屏:
from appium import webdriver
import time
desired_caps={}
# 模拟器安卓的版本号
desired_caps = {
"platformName": "Android", # 操作系统
"deviceName": "emulator-5554", # 设备 ID
"appPackage": "com.hehax.chat_create_shou", # app 包名
"appActivity": "com.junruy.wechat_creater.ui.activity.main.MainActivity", # app 启动时主 Activity
'noReset': True, # 是否保留 session 信息,可以避免重新登录
'unicodeKeyboard': True, # 使用 unicodeKeyboard 的编码方式来发送字符串
'resetKeyboard': True # 将键盘给隐藏起来
}
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
几个你用得着的命令: