爬虫常见两种情况:第一种情况,爬虫伪装成浏览器,向服务器要数据;第二种情况,在服务器往浏览器发送数据时,爬虫从中拦截,获取信息。
这两种情况,无论是暗号(参数)不对还是行为不对,都会被服务器辨认。那么有没有什么办法可以做到险些毫无陈迹地爬取数据呢?答案是有的。
目前,Android App重要有两种实现形式。第一种是Android原生App。这种App的全部或者大部门内容利用Android提供的各个接口来开辟,例如Android版的微信就是一个Android原生的App。第二种是基于网页的App。这种App本质上就是一个浏览器,里面的全部内容实际上都是网页。例如,12306的App就是这样一种基于网页的App。
Android原生App爬虫(以下简称App爬虫)可以直接读取Android原生App上面的文本信息。
App爬虫可以实现自动滚动屏幕,自动单击进入详情页。凡是人可以对手机举行的操纵,App爬虫都可以举行。
UiAutomator是Google官方提供的Android自动化图形接口测试框架。通过它可以实现对Android装备屏幕的各种操纵,或者直接从屏幕上读取笔墨。大部门体系版本大于4.1的Android体系,都会内置UiAutomator。小米手机原装的MIUI体系除外,MIUI体系UiAutomator被移除了,需要刷开辟版或者换其他体系才能利用。
一、环境搭建
1. 安装JRE
要利用UiAutomator操纵Android手机,首先需要在计算机上安装Android的软件开辟工具包(Software Development Kit, SDK)。要安装Android SDK,首先需要安装Java运行时环境(JavaRuntime Environment, JRE)。
对于Mac OS,利用Homebrew安装Java开辟套件(Java SE Development Kit,JDK)。JRE包含在了JDK里面:
- brew update
- brew cask install java
复制代码 对于Ubuntu,利用如下命令直接安装JRE:
- sudo apt-get update
- sudo apt-get install default-jre
复制代码 对于Windows,可以访问http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html下载JRE 8。在这个页面,首先选择“Accept License Agreement”单选按钮,根据自己的体系下载对应的安装步伐,32位体系下载并安装Windows x86;64位体系下载并安装Windows x64。安装过程不需要修改任何设置,全部单击“Next”按钮即可完成。
2. 安装Android SDK
安装完成JRE以后,再来安装Android SDK。请打开https://developer.android.google.cn/studio/index.html,这是Android开辟者中国官网,在中国可以直接打开。打开网页,拖到最下方,在“仅获取命令行工具”中下载自己体系对应的SDK。
下载的是一个.zip格式的压缩包,将之解压可以得到一个名为tools的文件夹。
在Mac OS与Ubuntu的终端输入并实行如下命令:
- cd ~/python/sdk
- bin/sdkmanager "platform-tools"
复制代码 Windows体系直接在tools文件夹中打开CMD窗口,并输入命令:
- bin/sdkmanager.exe "platform-tools"
复制代码 输入完成命令并按Enter键,可以看到在终端窗口弹出安装协议,输入y并按Enter键即可安装“platform-tools”。
需要留意的是,这里实行这个命令时,步伐会从Google获取一些数据,此时可能会由于网络问题导致失败。如果遇到网络问题,那么就需要利用能访问Google的代理,而且命令也需要做一些修改,修改为:
- bin/sdkmanager.exe "platform-tools" --proxy=http --proxy_host=代理IP --proxy-port=代理端口
复制代码 安装完成以后,会在文件夹下出现一个“platform-tools”文件夹。如今需要将tools文件夹和platform-tools文件夹添加到体系的环境变量中。
3. 设置环境变量
对于利用Mac OS或Ubuntu体系并安装了zsh和Oh-my-zsh的小伙伴,请打开~/.zshrc并检查是否已经有export PATH开头的一句话,如果有,请修改为下面所示的代码这样,其中的tools和platform-tools文件夹的地址请改为实际地址:
- export PATH="/Users/redhat/book/sdk/platform-tools:/Users/redhat/ book/sdk/tools:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
复制代码 如果没有,请添加进去,然后保存,并在终端中实行:
上面这种方式可永久性添加环境变量,只需要做一次。
如果是Mac OS或者Ubuntu体系且没有安装zsh和Oh-my-zsh的小伙伴,或者想临时添加环境变量举行测试,可直接在终端实行下面代码,将tools和platform-tools的地址改为实际地址:
- export PATH=$PATH:/Users/redhat/book/sdk/platform-tools:/Users/redhat/book/sdk/tools
复制代码 需要留意的是,这种方法是临时添加环境变量,当前的终端窗口不能关闭。一旦关闭再重新打开,就需要再一次实行上面的代码。
对于Windows,打开恣意一个文件夹,并在左侧导航窗口中右键单击“计算机”,选择“属性”命令,打开属性面板。在属性面板左侧选择“高级体系设置”选项,进入“高级”选项卡,最后单击右下角的“环境变量”按钮进入“环境变量”对话框,按照实际目次配置即可(个别Windows电脑,配置完环境变量需要重启见效)。
4. 开启开辟者模式
要通过计算机控制手机,还需要打开Android手机的开辟者模式。以小米手机的MIUI开辟版和Android原生体系为例,如何开启开辟者模式。
对于小米手机MIUI开辟版,依次进入“体系设置”-“我的装备”-“全部参数”,快速一连单击“MIUI版本”这一栏5次,开辟者模式就会打开。打开以后,回到“体系设置”主界面,依次进入“更多设置”-“开辟者选项”。在“开辟者选项”中分别打开“USB调试”、“USB安装”和“USB调试(安全模式)”这几个开关,体系会弹出告诫,选择允许。
对于Andorid原生体系,以Google生产的Nexus为例。打开“体系设置”,进入最下方的“体系”,打开体系信息界面。拖动最下方,找到“关于手机”并点击,进入手机状态界面。
由于各大厂商对Android体系险些都有自己的定制化,因此不能在这里一 一列举全部型号手机开启开辟者模式的操纵。对于没有提及的手机型号,请通过网络搜索。
设置好环境变量以后,在终端窗口输入“uiautomatorviewer”并按Enter键,如果可以弹出图所示的UI Automator Viewer窗口,表明环境设置乐成。
将Android手机连接到计算机上,保持手机屏幕为亮起状态,单击UI Automator Viewer左上角文件夹右侧的手机图标,如果可以大概看到手机屏幕出如今窗口中,则表现齐备顺利,环境搭建乐成完成。如果在这个过程中手机弹出了任何告诫窗口,都选择“运行”或者“确定”。
二、利用Python操纵手机
要利用Python来操纵UI Automator从而控制手机,需要安装一个第三方库。这个库的名字就是uiautomator,利用pip举行安装
安装完成以后运行Python并导入uiautomator:
- from uiautomator import Device
- device = Device()
- print(device.dump())
复制代码 由于是第一次运行,uiautomator会往手机中安装两个没有图标的步伐。有一些手机体系可能会弹出窗口询问是否允许安装,单击“继续安装”按钮。安装完成以后,可以看到终端窗口出现了类似于XML的内容。这说明uiautomator这个第三方库乐成安装。此时就可以利用Python控制手机了。
有一点需要特殊说明,UI Automator Viewer与Python uiautomator不能同时利用。一旦Python的uiautomator运行过一次,它安装的两个文件就会在手机配景运行。这两个文件会占用Android内部的一个叫作UI hierarchy的东西,从而导致SDK自带的UI Automator Viewer一旦尝试获取手机屏幕就会报错,如图:
一旦出现这种情况,就需要手动结束Python uiautomator安装的两个文件的进程,或者重启手机才能继续利用UI Automator Viewer。这两个进程的名字分别为“uiautomator”和“com.github.uiautomator.test”。
与Selenium一样,要操纵手机上面的元素,首先要找到被操纵的东西。以打开微信为例,首先翻到有微信的那一页。
编写如下代码:
- from uiautomator import Device
- device = Device()
- device(text='微信').click()
复制代码 运行以后可以看到,微信自动被点击并打开。
如果计算机上面只连接了一台Android手机,那么初始化装备连接只需要利用device = Device()即可。那么如果计算机上连接了许多台手机,该怎么办呢?此时就需要指定手机的串号。要查看手机串号,需要在终端输入以下命令:
从输出的内容可以看到手机的串号。只要不是人为去修改,在正常情况下,每一台手机的串号都是不一样的。因此可以以为串号与手机是一一对应的。将手机的串号(比如,'123456abccde')作为device的参数,就可以指定控制对应的手机:
- device = Device('123456abccde')
复制代码 在初始化了装备连接以后,全部的操纵都是通过这个变量device的各个方法或者属性来完成的。device的参数text=“微信”称为“Selector”,也就是选择器。通过不同的选择器来选定不同的元素,并对元素举行不同的操纵。
三、选择器
如何知道有哪些选择器可供利用呢?请实行以下代码:
- from uiautomator import Device
- device = Device()
- print(device.dump())
复制代码 此时终端会以XML输出当前手机屏幕表现的窗口布局信息。
这里的XML就相当于网页中的HTML,用来描述窗口上面各个部门的布局信息。XML的格式与HTML非常像,格式为:
- <标签 属性1="属性值1" 属性2="属性值2">文本</标签>
复制代码 其中的各个属性和属性值,就是选择器操纵的对象。这里的不同属性包括但不限于“text”“class”“description”“resource-id”和“package”。
在uiautomator中,也有选择器和这些属性一一对应。其中,选择器“className”对应“class”标签;选择器“packageName”对应“package”标签;选择器“resourceId”对应“resource-id”标签。所以要选择一个元素,可能有如下的写法:
- device(packageName='com.android.systemui')
- device(className='android.widget.FrameLayout')
- device(resourceId='com.android.systemui:id/clock')
- device(text='短信')
- device(index='3', resourceId='com.android.systemui:id/mobile_combo')
复制代码 可以用一个标签来作为选择器,也可以同时利用多个标签来更精确地描述某一个元素。一般来说,操纵一个有笔墨的元素,重要是利用text这个属性;如果是从屏幕上读笔墨,就利用其他的属性。
四、操纵
在选择好元素以后,就需要对它举行操纵。最常见的操纵如下:
• 获得屏幕笔墨;
• 滚动屏幕;
• 滑动屏幕;
• 点击屏幕;
• 输入笔墨;
• 判断元素是否存在;
• 点亮关闭屏幕;
• 操纵实体按键;
• watcher。
1. 获得屏幕笔墨
如果要从Android手机上读取当前屏幕上表现的文本内容,用到的是一个元素的“.text”属性。
2. 滚动屏幕
滚动屏幕对应的操纵为“.scroll()”。它的操纵对象是一个可以滚动的对象。如果手动操纵可以把屏幕向上滚动,那么屏幕上应该至少有一个元素是可以滚动的,因此选择器可以写为:
device(scrollable=True)
那么向上滚动一屏可以写为:
device(scrollable=True).scroll.vert.forward()
如果想向下滚动一屏,则需要把forward()换为backward():
device(scrollable=True).scroll.vert.forward()
由于向上、向下是“垂直方向”,所以代码中利用了vert,这是英语单词vertical(垂直的)的简写。可能有些App会出现左右滚动的情况,这时间就需要利用horiz,这是英语单词horizontal(水平的)的简写。于是,向左及向右滚动就可以写为:
device(scrollable=True).scroll.horiz.forward() #向右滚动
device(scrollable=True).scroll.horiz.backward() #向左滚动
有一点需要留意,由于滚动一屏时,有可能前一屏最下面的元素滚动以后刚好到了后一屏的最上面,因此可能出现重复获取,在实际利用时要留意去重处置处罚。
3. 滑动屏幕
在某些情况下,整个窗口布局的XML里面,全部元素的scrollable属性值全部都是False,例如小米手机的桌面。在这种情况下,没有办法利用“scrollable=True”来左右滚动桌面,于是就需要利用根据坐标来滑动桌面的“.swipe()”方法。
在Android体系的屏幕上,左上角为坐标原点(0, 0),越向下,y轴数字越大;越向右,x轴数字越大。
“.swipe()”这个方法操纵的对象是整个手机屏幕,所以不需要为device设定选择器。“.swipe()”的用法为:
device.swipe(400, 600, 0, 600)
它接收4个参数,分别为起始点x坐标,起始点y坐标,尽头x坐标,尽头y坐标。对于左右滑动来说,只需要改变x坐标即可。如果要表现右边的一屏,那么起始点的x坐标要大于尽头的x坐标。如果要表现左边的一屏,起始点的x坐标要小于尽头的x坐标。
如果在实际写代码的时间搞不清x坐标哪个大,就亲自把手放在屏幕上滑动举行查看。如果要表现右边的一屏,那么会首先把手放在屏幕右侧,按住然后往左移动,所以此时起始点的x坐标要大一些。
4. 点击屏幕
选择一个元素以后,除了获取它上面的笔墨外,还可以点击。就如同前面通过点击打开微信一样。点击操纵“.click()”和“.long_click()”分别对应短按点击和长按点击,它们可以直接应用于一个被选择出来的元素上。例如:
device(text='微信').click()
device(text='微信').long_click()
点击操纵也可以直接应用于坐标位置。例如:
device.click(230, 567) #第1个参数为横坐标x轴,第2个参数为纵坐标y轴
device.long_click(230, 567) #第1个参数为横坐标x轴,第2个参数为纵坐标y轴
在某些App中,可能某一个元素并没有一个独特的标记来让选择器选择。这个时间就可以直接利用坐标来操纵。
5. 输入笔墨
既然进入了搜索界面,那就需要搜索内容了。输入文本利用的操纵是“.set_text()”。
因此可以用这个resource-id来作为选择器定位到搜索框,再输入文本。例如搜索名为“大秦重工”的博主,那么就利用以下代码:
device(resourceId='com.taptap:id/input_box').set_text('大秦重工')
6. 判断元素是否存在
由于手机上面的各个元素加载是需要一定时间的,如果在元素加载出来之前就对其举行操纵,就会导致步伐报错,在操纵一个元素之前,先判断一下它是否存在是比较明智的做法。判断元素是否存在,利用“.exists”属性。如果存在,值为True,否则为False。其用法为:
input_box = device(resourceId='com.taptap:id/input_box')
if input_box.exists:
input_box.set_text('大秦重工')
else:
print('搜索框不存在')
如果元素只是由于没有来得及加载出来而不存在,并不是屏幕界面错误,那么还可以等待它加载出来以后再举行更多操纵。利用到的方法是“.wait.exists()”,其中exists还可以设置等待超时时间。例如:
search_result = device(text='大秦重工')
if search_result.wait.exists(timeout=20000)
search_result.click()
else:
print('元素不存在')
等待笔墨为“大秦重工”的元素出现,如果在20s以内出现了这个元素,就点击它,否则就打印“元素不存在”的提示。需要留意的是,这里“.exists()”的超时时间单位为ms。所以要等待20s,就需要输入20000。
7. 点亮关闭屏幕
利用“.wakeup()”方法和“.sleep()”方法可以点亮或者关闭屏幕。当手机屏幕处于关闭状态时,利用“.wake()”方法可以让屏幕点亮;当手机屏幕处于点亮状态时,利用“.sleep()”方法可以将其关闭。其用法为:
device.wakeup() # 点亮屏幕
device.sleep() # 关闭屏幕
如果要检查当前手机屏幕是开启状态还是关闭状态,就需要利用“.screen”属性。它的值为“on”,表现当前手机屏幕亮起;值为“off”,表现当前手机屏幕关闭。其用法如下:
if device.screen == 'on':
print('当前手机屏幕为点亮状态')
elif device.screen == 'off':
print('当前手机屏幕为关闭状态')
8. 操纵实体按键
Android一般自带不少实体按键,利用Python的uiautomator可以模拟这些按键被按下的状态。其利用方法为:
device.press.实体按键名称()
常见的实体按键名称和作用如表:
例如,如今的手机屏幕处于关闭状态,需要点亮屏幕,除了利用“.wakeup()”方法以外,还可以模拟按下电源键:
device.press.power()
又例如需要增大音量,那么就模拟按下音量增大键:
device.press.volume_up()
9. watcher
利用Android手机的时间,经常会遇到这样的情况:手机用着用着,突然弹出一个对话框,提示当前App有新版本可用。对于用户来说,遇到这种对话框,又不想升级,那么按一下返回键就可以临时把这个对话框关闭。但是这种对话框对于利用步伐来操纵手机的场景来说,就是一个灾难。
device.watcher('In_Detail_to_Search').when(text='我的天下 Minecraft').when(text='预约').press.back()
这一段代码表现注册了一个名字为“In_Detail_to_Search”的watcher,这个watcher要实行的操纵是按下实体按键的返回键。它被激活需要满意3个条件。
(1)代码出现了找不到元素的情况,即将报错。
(2)当前屏幕上某个元素的文本为“我的天下Minecraft”。
(3)当前屏幕上某个元素的文本为“预约”。
watcher是一种特殊的对象,它被注册以后就不停悄悄地等待,只有在步伐里面的某一处代码出现了找不到元素的情况下才会被触发,并按照注册次序依次举行检查。如果找到了符合条件的watcher,就会实行这个wather对应的操纵。如果全部watcher都检查完依然没有找到符合条件的情况,那么就继续抛出找不到元素的非常。
watcher的第1个参数表现这个watcher的名字,可以是任何字符串。但是不同的watcher的名字不能雷同。背面的全部“when()”表现满意这个watcher所需要的条件。每个when()之间是“与”的关系,只有全部的when里面的选择器同时满意,这个watcher才会被触发,并实行最后的语句。
10. 其他操纵
Android的UI Automator框架可以实现全部图形界面的操纵,只要是人能做的它都能做。Python的uiautomator库完备实现了这些操纵。但是由于一些操纵对于开辟爬虫来说并没有什么作用,例如双指缩放屏幕、旋转屏幕等操纵。感兴趣的小伙伴可以参阅uiautomator的官方文档。
--------------------------------------
没有自由的秩序和没有秩序的自由,同样具有粉碎性。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |