推荐教学:http://www.python3.vip/tut/auto/appium/01/

配置环境

1、安装client编程库:

自动化程序需要调用客户端库和 Appium Server 进行通信。

  1. pip install appium-python-client

2、安装Appium Server:

appium下载地址:https://github.com/appium/appium-desktop

Appium Server 是用 nodejs 运行的,基于js开发出来的。Appium组织为了方便大家安装使用,制作了一个可执行程序 Appium Desktop,把 nodejs 运行环境、Appium Server 和一些工具打包在里面了,只需要简单的下载安装就可以了。

3、安装JDK:

官方下载比较麻烦,所以我这里提供一个链接:http://www.sousou88.com/spec/oraclejdk.html 搜索jdk8,下载win x64版本

安装好之后,还需要添加一个系统环境变量 JAVA_HOME ,值为jdk安装目录。

  1. JAVA_HOME C:\Program Files\Java\jdk1.8.0_281

Appium - 图1

4、安装 Android SDK:

通过Android Studio来安装Android SDK,好比我们使用anaconda来安装Python一样,效率更高,更安全。https://developer.android.com/studio

对于安卓APP的自动化,Appium Server 是需要 Android SDK的。因为要用到里面的一些工具,比如 要执行命令设置手机、传送文件、安装应用、查看手机界面等。

安装后启动,会出现安装sdk的页面,进行安装即可(1.75G,可能需要点时间)。
image.png
安装完成!image.png

安装完成之后,我们还需要给它添加系统环境变量 ANDROID_HOME ,值为sdk的目录。

  1. ANDROID_HOME C:\Users\Administrator\AppData\Local\Android\Sdk

Appium - 图4
如果还是没找到可以试用everything,搜索 Android\Sdk 第一个就是你的目录了。(AppData目录一般是隐藏文件)
image.png
另外还需要添加 环境变量 PATH ,加入adb.exe 所在目录(platform-tools文件夹所在目录)

  1. C:\Users\Administrator\AppData\Local\Android\Sdk\platform-tools

image.png
我这里的路径是 C:\Users\Administrator\AppData\Local\Android\Sdk\platform-tools
image.png
记得保存,并确定。之后,我们打开命令行窗口,输入 adb,看下是否添加成功。
image.png
显示这样,就说明添加成功。

5、连接手机

我们有两种方式,一种是使用安卓模拟器,一种是使用真机;

方式一、模拟器连接

设置模拟器:

打开模拟器,本人用的是夜神模拟器,设置如下(图文教程):

  • 1)设置 - 关于平板电脑 - 版本号(不是Android版本)- 连续点击五次开启开发者模式;
  • 2)返回后在设置里找到 开发者选项 - 打开 USB调试
  • 3)把nox_adb程序添加到系统环境变量
  • 4} 确定
    1. nox_adb D:\Program Files\Nox\bin
    Appium - 图9
    进入cmd后,输入adb devices,会显示如图,并且守护进程成功启动的说明。
    注意:模拟器处于启动状态!
    Appium - 图10
    此时,我们进入模拟器目录(D:\Program Files\Nox\bin),在地址栏里输入 cmd,就可以直接打开小黑框并进入该路径。然后输入 nox_adb.exe connect 127.0.0.1:62001 进行连接。

    windows进入当前目录的终端的方法: 1、在此文件夹窗口内空白区域右键单击(需要同时按住Shift),从菜单中选择"在此处打开命令行窗口"的项; 2、在当前目录的地址栏里直接输入cmd,回车即可。

Appium - 图11

不同模拟器的链接方式: 夜神模拟器:adb connect 127.0.0.1:62001 逍遥安卓模拟器:adb connect 127.001:21503 天天模拟器:adb connect 127.0.0.1:6555 海马玩模拟器:adb connect 127.0.0.1:53001 网易MUMU模拟器:adb connect 127.0.0.1:7555

注意:powershell和命令提示符的用法不一样(多个引号),具体看下面两张图
先进盘符;接着cd进入目录;之后链接。
Appium - 图12
Appium - 图13Appium - 图14
再次输入adb devices,如下图所示就表示成功连接了~(这里是我们之前添加了platform-tools目录到环境变量,如果没有加,需要cd进入目录后在执行)里面多的一行 emulator-5554 device 是我另外一个雷电模拟器,请忽视。
image.png

设置appium:

最后,我们打开 appium客户端,点击 Start Server ,点击搜索按钮
image.png
在 Desired Capabilities 中输入对应参数,之后点击 Start Session 即可(保持模拟器打开状态),其中 appPackage 和 appActivity 获取方式在下面
image.png
也可以使用右侧的JSON格式写入,我的参数如下:

  1. {
  2. "platformName": "Android",
  3. "platformVersion": "7.1",
  4. "deviceName": "xxx",
  5. "appPackage": "com.taobao.idlefish",
  6. "appActivity": "com.taobao.fleamarket.home.activity.MainActivity",
  7. "unicodeKeyboard": true,
  8. "resetKeyboard": true,
  9. "noReset": true,
  10. "newCommandTimeout": 6000,
  11. "automationName": "UiAutomator2"
  12. }

当你看下面的页面,就说明配置成功了 🎉
image.png

方式二、真机连接:

上述的软件环境都准备好以后,要自动化手机APP,需要:

  1. 在你运行程序的电脑上 用USB线 连接上你的安卓手机;
  2. 进入 手机设置 -> 关于手机 ,不断点击 版本号 菜单(7次以上);
  3. 退出到上级菜单,在开发者模式中,启动USB调试;

如果手机连接USB线后,手机界面弹出 类似 如下提示。

Appium - 图19

选择 允许USB调试。

连接好以后,打开命令行窗口, 执行 adb devices -l 命令来列出连接在电脑上的安卓设备。
如果输出类似如下的内容:

表示电脑上可以查看到 连接的设备,就可以运行自动化程序了。

有时候会报错 adb server version (31) doesn’t match this client (41); killing… 点击这里解决

上面的链接模拟器的时候,我们使用了 appium来启动app,不过我们通常使用的是Python进行操作。下面我们来个实例看下

appPackage和appActivity 获取方式:

首先确保你已经在模拟器打开并显示该APP,使用 terminal依次输入:(如图)

  1. #方式一:
  2. adb shell
  3. dumpsys activity | grep mFocusedActivity

image.png
当然有时候后面的appActivity是点开头的
image.png

  1. #方式二:
  2. adb shell dumpsys activity activities

其中方式二显示的是当前所有在运行的任务栈,并可查看栈中所有的 Activity 的列表;我们找到 mFocusedActivity 表示当前运行的app程序。
image.png

结果: appPackage:com.taobao.idlefish appActivity:com.taobao.fleamarket.home.activity.MainActivity

定位元素

连接完成之后,我们就要去找元素,并对元素进行操作。,首先说下我们定位元素用到的工具:

使用的工具:

常用的查看工具是: Appium Desktop 中的 Appium Inspector 和 Android Sdk包中的 uiautomateviewer ;同时两种工具分别对应两种定位元素的方式(一一对应搭配使用)。

注意:两个软件不可以同时打开,否则会报错。

Appium Inspector(常用)

这是 appium 自带的元素查找器,有selenium基础的用这个上手快,不过没有下面的那个好用(有时候会遇到找不到元素),不过它有自己的优势,就是支持搜索验证(类似于F12之后,我们使用ctrl+f来验证元素是否唯一)

注意:有个问题,就是只要运行py后,再来寻找元素,就需要重启。

image.png

uiautomateviewer(高效)

使用everything 搜索 \Android\Sdk\tools\bin ,在bin目录下就可以找到 ,双击打开 uiautomateviewer.bat,页面如下图:
image.pngimage.png

定位元素:

Selenium Web(常用)

image.png

  1. # id # resource-id 属性 斜杠前面的是包名,可以省略
  2. driver.find_element_by_id('search_bar_layout')
  3. # class_name 类似web里面的tagname,一般为多个,所以用了elements
  4. driver.find_elements_by_class_name('android.widget.RelativeLayout')
  5. # accessibility_id # content-desc (描述)属性
  6. driver.find_element_by_accessibility_id('衬衫')
  7. # xpath 没有selenium里的可靠,经常变,不建议使用
  8. driver.find_element_by_xpath('//ele1/ele2[@attr="value"]') #

上面的方法实际上的步骤是程序发送请求 - Appium server转化为代理程序 - 让uiautomator调用安卓的相应函数,其实我们可以跳过appium,直接使用uiautomator里的方法。下面我们看看如何使用,下面给出几个例子,更多的方法可以参考官方文档。

UI Automator API(高效)

官方文档:https://developer.android.google.cn/training/testing/ui-automator image.png

主要有三大模块,查看器就是我们前面使用的查找元素的工具uiautomateviewer;设备状态是设备相关的,比如音量、返回菜单、通知栏等;我们重点查看 UI Automator API 里面的 UiSelector,即选择元素的方式(当然,这里是java语法)。
image.png

点进去就可以看到所有选取元素的方法汇总表,这里拿几个常见的举例:

  1. code = 'new UiSelector().text("热门").className("android.widget.TextView")'
  2. driver.find_element_by_android_uiautomator(code).click()

多种限制条件用点进行连接,比如上面我们用的text和classname。

除了根据文本text,还有

  • textContains 根据文本包含什么字符串
  • textStartsWith 根据文本以什么字符串开头
  • textmartch 使用正则表达式 选择一些元素
  • instance 是匹配的结果所有元素里面 的第几个元素
  • index 则是其父元素的几个节点,类似xpath 里面的*[n]
  • childSelector 可以选择后代元素

操作元素:

click、tap、send_keys、swipe、press_keycode

最常见的操作之一,使用 WebElement 对象的 click 方法, 示例代码就讲过,不再赘述。

WebElement 对象的 tap 方法和 click 类似,都是点击界面。但是最大的区别是, tap是 针对坐标(bounds的值) 而不是针对找到的元素。
image.pngimage.png
它有两个参数,第一个是点击的坐标,类型是列表,最多可以有5个元素,代表5根手指点击5个坐标。第二个参数 表示tap点按屏幕后停留的时间。如果点按时间过长,就变成了长按操作了。

  1. # 如果想点击中间区域,我们计算一下就可以了 (637-27)/2,(162-108)/2 就得到选择区域中间坐标
  2. driver.tap([(306.5,27)],300) # 300代表停留时长,表示长按

swipe:前面4个参数是滑动起点和终点的x、y坐标。第5个参数duration是滑动从起点到终点坐标所耗费的时间。

  1. driver.swipe(start_x=x, start_y=y1, end_x=x, end_y=y2, duration=800)

press_keycode:模拟按键动作,这里一般使用数字,如果不清楚数字代表什么,点我

  1. from appium.webdriver.extensions.android.nativekey import AndroidKey #导入包
  2. driver.press_keycode(66) # 输入回车键(66代表回车),确定搜索

Appium的 TouchAction 类提供了更多的手机操作方法,比如:长按、双击、移动等,更多资料,点我

  1. from appium.webdriver.common.touch_action import TouchAction
  2. # 下面就是一个长按的例子
  3. actions = TouchAction(driver) # 初始化
  4. actions.long_press(element) # 使用的方法
  5. actions.perform() # 结尾必须加

driver.open_notifications() 打开通知栏,关闭的方式可以试用滑动,也可以使用返回按键。

adb命令:

官方文档:https://developer.android.google.cn/studio/command-line/adb#move

adb 全程 Android Debug Bridge,这个adb 使用非常广泛。它可以与 Android 手机设备进行通信,它可进行各种设备操作。

比如: 安装应用和调试应用,传输文件,甚至登录到手机设备上shell的进行访问,就像远程登录一样。这个adb 在 sdk的 platform-tools 目录下面, 请大家确保路径在path环境变量中。

Appium 对anroid的自动化就非常依赖这个adb工具。 执行自动化过程中,有很多内部操作,比如获取设备信息,传送文件到手机,安装apk,启动某些程序等,都是通常这个adb实现的。

  1. adb devices -l # 查看链接的设备
  2. adb shell ls /sdcard # 查看目录
  3. adb push wv.apk /sdcard/wv.apk # 上传
  4. adb pull /sdcard/new.txt # 下载
  5. adb shell screencap /sdcard/screen.png # 截屏 截屏后可以使用adb pull下载下来

既然这是个命令,就可以使用 Python的 os.system() 或者 subprocess 来自动化调用它,完成我们的各种自动化需求。

比如,我们自动化过程中,可能需要截屏手机,并且下载到指定目录中,就可以在我们的Python程序中这样写

  1. import os
  2. os.system('adb shell screencap /sdcard/screen3.png && adb pull /sdcard/screen3.png')

更多adb命令,点我

Python 运行示例

首先要打开appium,点击 Start Server ,等待自动化程序给它发出指令(py脚本通过appium来控制模拟器)。
image.png
然后运行py文件,appium会自动在模拟器里安装一个程序 Appium Setting用来和模拟器连接,安装后会继续运行脚本,打开app程序,进行脚本里的程序。

闲鱼加了反爬,有些元素找不到,所以我用酷安APP来做实例演示

提示:元素找完了之后再运行py,因为py运行后就会导致报错,这时候就需要重启uiautomatorviewer。

酷安搜索

  1. from appium import webdriver
  2. from appium.webdriver.extensions.android.nativekey import AndroidKey
  3. import time
  4. desired_caps = {
  5. 'platformName': 'Android', # 被测手机是安卓
  6. 'platformVersion': '7.1.2', # 手机安卓版本
  7. 'deviceName': 'xxx', # 设备名,安卓手机可以随意填写
  8. 'automationName': 'Appium', # 指定引擎 UiAutomator2,默认 Appium
  9. # 'app': r'D:\\OneDrive/software/apk/Cool.apk' # apk本地文件路径
  10. 'appPackage': 'com.coolapk.market', # 启动APP Package名称
  11. 'appActivity': '.view.main.MainActivity', # 启动Activity名称
  12. 'unicodeKeyboard': True, # 使用unicode输入法,需要输入中文时填True
  13. 'resetKeyboard': True, # 执行完程序恢复原来输入法
  14. 'noReset': True, # 不要重置App
  15. 'newCommandTimeout': 6000,
  16. }
  17. # 连接Appium Server,初始化driver 4723来自于appium的端口
  18. driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
  19. time.sleep(3)
  20. driver.tap([(189, 72)]) # 点击搜索框
  21. time.sleep(1)
  22. # Appium ----------------------------------------
  23. driver.find_element_by_class_name(
  24. "android.widget.EditText").send_keys("微信") # 定位并输入搜索内容
  25. # UiAutomator2 -----------------------------------
  26. code = 'new UiSelector().resourceId("com.coolapk.market:id/search_text")' # 定位元素
  27. driver.find_element_by_android_uiautomator(code).send_keys('微信') # 操作元素

刷抖音(swipe)

  1. from appium import webdriver
  2. from appium.webdriver.extensions.android.nativekey import AndroidKey
  3. import time
  4. desired_caps = {
  5. 'platformName': 'Android', # 被测手机是安卓
  6. 'platformVersion': '7.1.2', # 手机安卓版本
  7. 'deviceName': 'xxx', # 设备名,安卓手机可以随意填写
  8. 'automationName': 'Appium', # 指定引擎 UiAutomator2,默认 Appium
  9. # 'app': r'D:\\OneDrive/software/apk/Cool.apk' # apk本地文件路径
  10. 'appPackage': 'com.ss.android.ugc.aweme', # 启动APP Package名称
  11. 'appActivity': '.splash.SplashActivity', # 启动Activity名称
  12. 'unicodeKeyboard': True, # 使用unicode输入法,需要输入中文时填True
  13. 'resetKeyboard': True, # 执行完程序恢复原来输入法
  14. 'noReset': True, # 不要重置App
  15. 'newCommandTimeout': 6000,
  16. }
  17. # 连接Appium Server,初始化driver 4723来自于appium的端口
  18. driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
  19. driver.implicitly_wait(5) # 隐式等待5秒
  20. class Mobile_Action:
  21. # 1、向上滑动
  22. def swipe_up(self):
  23. size = driver.get_window_size() # 获取手机分辨率
  24. width = size['width'] # 屏幕的宽
  25. height = size['height'] # 屏幕的高
  26. x1 = width/2 # 滑动开始的x轴中心坐标
  27. y1 = height/10*6 # 滑动起始的y轴坐标
  28. y2 = height/10 # 向上滑动的y轴终点坐标
  29. driver.swipe(x1, y1, x1, y2, 400) # 4秒的滑动时间
  30. time.sleep(3) # 每个视频看3秒
  31. if __name__ == "__main__":
  32. douyin = Mobile_Action()
  33. time.sleep(6) # 开屏广告时间
  34. for i in range(5):
  35. douyin.swipe_up()

难点主要在于元素的定位,有些元素是动态的,所以就要想其他方法去找。

常见报错:

Error obtaining Ul hierarchy

Reason: Error while obtaining UI hierarchy XML file com. android. ddmlib SyncException: Remote object doesn t exist
image.png
问题解决办法:
如果是真机,直接插拔USB,然后重新连接,一般都会好
如果是模拟器,在命令窗口中将adb kill掉,输入:adb kill-server,然后重新运行uiautomatorviewer