• 前言
    • 个人觉得uiautomator2的运行方式比appium要简单许多,因为appium依赖性方较多会遇到很多麻烦,所以听闻这个工具也有不少人在使用就一起来了解了解吧~
  • 环境部署(Android篇)
    • 电脑上需要有已配置好的adb的环境(网上教程很多,这里就不细讲了)
    • 安装python中的uiautomator2库

      pip install -U uiautomator2       出现Successfully installed的标识就说明安装成功   

    • 往手机上安装atx-agent

      1)使用数据线连接手机使用adb命令查出序列号    adb devices

      2)在python中编写启动脚本并运行成功,就可以直接在手机上直接安装atx(安装好后会出现一个小汽车的图标)

      1 import uiautomator2 as u2
      2 d = u2.connect_usb('9YS0220813028584')# 按序列号连接手机
      3 print(d.info)
      4 d.app_start('包名')# 启动app(包名)   如何获取app的包名可以参考我的其他文章

       

       3)安装weditor

      pip3 install weditor==0.6.4

       4)启动weditor

      python -m weditor

      注:输入命令后会自动打开浏览器并显示weditor工具页面,默认选中Android,在后面输入框中输入步骤2)查出的序列号例如“9YS0220813028584”来连接手机,点击【Connect】连接,出现小绿叶🍀表示连接成功

        

  • 环境部署(iOS篇)
    • 介绍:经过研究uiautomator2后发现可以借助weditor工具来使iOS手机脱离Mac系统在Windows上成功连接iOS手机并且正常运行自动化脚本!
    • 前提:必须要借助Mac的xcode来给iOS手机上编译WebDriverAgent !!!(关于如何在iOS手机上编译WDA可参考我的其他文章,链接附上 https://www.cnblogs.com/pengxiaojie/p/17097509.html) 

    • webdriveragent安装包可以在我的网盘里直接下载:https://pan.baidu.com/s/1iSchATcCwiOz6EHUpz84Vg?pwd=p999               提取码:p999

    • 1)安装tidevice

      pip install tidevice

      2)通过cmd命令查找手机上已安装好的wda的包名(包含WebDriverAgent标识的就是wda包名,例:图中第7行)

      tidevice applist

      

      3)cmd命令启动WDA运行(启动后勿关闭)

      tidevice wdaproxy -B com.pengit.WebDriverAgentRunner.xctrunner --port 8100

      4)启动weditor(启动后勿关闭)

      python -m weditor

      注:输入命令后自动打开浏览器并显示weditor工具页面,选择iOS后需要输入ip地址http://localhost:8100来连接手机 ,点击【Connect】连接,出现小绿叶🍀表示连接成功

      5)关于在python中启动iOS的命令如下:  

1 import wda
2 
3 d = wda.Client('http://localhost:8100')# 该地址为weditor中连接真机的ip
4 d.session().app_activate("包名") # 打开app(注意:Android和iOS的包名不一致,自己用命令查或问开发
5 d(label="我的").click()#进入APP点击我的

 

到这里关于uiautomator2的自动化环境就搭建好了! 若大家有疑问或着有好的想法大家可以在评论区留言一起讨论💀💀💀~~

  • 学习uiautomator2的简单使用:

  1.安装

pip install --upgrade --pre uiautomator2

  2.连接手机

查看代码
import json
import uiautomator2 as u2
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
# 设备信息
device_info = d.device_info
print("device_info",json.dumps(device_info,ensure_ascii=False))
d2 = u2.connect('192.168.61.148:5555') # 首次执行会往手机安装ATX软件
print(json.dumps(d2.info,ensure_ascii=False))

  3.启动一个app app_start函数

查看代码
 import json
import uiautomator2 as u2
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
result = d.app_start("com.xingin.xhs")
print("result",result)

   4.停用app

  app_stop 停用一个app,需要传入包名
  app_clear 清理并退出一个app。【需要登录的app不要用,会把app登录状态退出】
  app_stop_all 退出所有app。
  d.app_stop_all(excludes=['com.examples.demo']) 停用所有app除了包名com.examples.demo的。

查看代码
 import json
import uiautomator2 as u2
import time
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
result = d.app_start("com.xingin.xhs")
d.app_stop("com.xingin.xhs")
# 需要登录的app不要使用clear,会把数据都清空
d.app_clear('com.xingin.xhs')
time.sleep(10)
# stop all
d.app_stop_all()
# stop all app except for com.examples.demo
# d.app_stop_all(excludes=['com.examples.demo'])

  5.获取一个app信息

  app_info

查看代码
 import json
import uiautomator2 as u2
import time
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('019b86d626a0bb08') # alias for u2.connect_wifi('10.0.0.1')
# print(json.dumps(d.info,ensure_ascii=False))
app_info = d.app_info("com.xingin.xhs")
print(json.dumps(app_info,ensure_ascii=False))
# save app icon
img = d.app_icon("com.xingin.xhs")
img.save("icon.png")

  6.等待app运行

查看代码
 import json
import uiautomator2 as u2
import time
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
pid = d.app_wait("com.xingin.xhs") # 等待应用运行, return pid(int)
if not pid:
    print("com.xingin.xhs is not running")
else:
    print("com.xingin.xhs pid is %d" % pid)
pid2 = d.app_wait("com.xingin.xhs", front=True) # 等待应用前台运行
print("pid2",pid2)
pid3 = d.app_wait("com.xingin.xhs", timeout=20.0) # 最长等待时间20s(默认)
print("pid3",pid3)

  7.文件传输

  和adb pull和push差不多的功能。

查看代码
 # 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
# 外部往手机端推送
# push to a folder
# d.push("foo.txt", "/sdcard/")
# # push and rename
# d.push("foo.txt", "/sdcard/bar.txt")
# # push fileobj
# with open("foo.txt", 'rb') as f:
# d.push(f, "/sdcard/")
# # push and change file access mode
# d.push("foo.sh", "/data/local/tmp/", mode=0o755)
# 从手机内部pull出来
d.pull("/sdcard/foo.txt", "tmp.txt")
# FileNotFoundError will raise if the file is not found on the device
# d.pull("/sdcard/some-file-not-exists.txt", "tmp.txt")

  8.执行shell命令

查看代码
 import json
import uiautomator2 as u2
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
# 1、简单使用
output, exit_code = d.shell("pwd", timeout=60) # timeout 60s (Default)
print("output, exit_code", output, exit_code)
# Since `shell` function return type is `namedtuple("ShellResponse", ("output", "exit_code"))`
# so we can do some tricks
output = d.shell("pwd").output
exit_code = d.shell("pwd").exit_code
print("output",output)
print("exit_code",exit_code)
# 第一个参数可以是列表
output, exit_code = d.shell(["ls", "-l"])
print("output, exit_code", output, exit_code)
# 2、运行长时间运行的 shell 命令
r = d.shell("logcat", stream=True)
# r: requests.models.Response
import time
deadline = time.time() + 10 # run maxium 10s
try:
    for line in r.iter_lines(): # r.iter_lines(chunk_size=512, decode_unicode=None, delimiter=None)
        if time.time() > deadline:
            break
        print("Read:", line.decode('utf-8'))
finally:
    r.close() # this method must be called

  9.各种设备信息

查看代码
 import json
import uiautomator2 as u2
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
# 1、d.info
print(json.dumps(d.info,ensure_ascii=False))
# 2、device_info
print(json.dumps(d.device_info,ensure_ascii=False))
# 3、Get window size
print(json.dumps(d.window_size(),ensure_ascii=False))
# 4、print(d.app_current())
# 获取当前的应用信息。 对于某些 android 设备,输出可能为空(参见输出示例 3)
print(d.app_current())
# {'package': 'com.miui.home', 'activity': 'com.miui.home.launcher.Launcher'}
# 5、获取设备序列号
print(d.serial)
# 6、Get WLAN ip
print(d.wlan_ip)

 10.滑动、点击等操作

查看代码
 import json
import uiautomator2 as u2
import time
import random
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
# 1、粘贴板
d.set_clipboard('text', 'label')
print(d.clipboard)
# 2、开关屏幕
# d.screen_on() # turn on the screen
# d.screen_off() # turn off the screen
## 3、获取当前屏幕状态
screenOn = d.info.get('screenOn') # require Android >= 4.4
print("screenOn",screenOn)
## 4、按键
# d.press("home") # press the home key, with key name
# d.press("back") # press the back key, with key name
# d.press(0x07, 0x02) # press keycode 0x07('0') with META ALT(0x02)
# d.press("enter") # press keycode 0x07('0') with META ALT(0x02)
# 目前支持这些键名:
# home
# back
# left
# right
# up
# down
# center
# menu
# search
# enter
# delete ( or del)
# recent (recent apps)
# volume_up
# volume_down
# volume_mute
# camera
# power
## 5、解锁屏幕、结合weditor来搞
# d.unlock()
# import time
# time.sleep(5)
# d(text="1").click()
# d(text="1").click()
# d(text="1").click()
# d(text="1").click()
## 5、点击:
# 按百分比x,y点击
# d.click(x, y)
# d.click(0.362, 0.41)
# 双击
# d.double_click(0.491, 0.125)
# d.double_click(0.491, 0.125, 0.1) # default duration between two click is 0.1s
# 长按着
# d.long_click(x, y)
# d.long_click(x, y, 0.5)
# 滑动
# d.swipe(sx, sy, ex, ey)
# d.swipe(sx, sy, ex, ey, 0.5) # swipe for 0.5s(default)
# 滑动
# d.swipe_ext("left") # 手指右滑,4选1 "left", "right", "up", "down"
# d.swipe_ext("right") # 手指右滑,4选1 "left", "right", "up", "down"
# d.swipe_ext("right", scale=0.9) # 默认0.9, 滑动距离为屏幕宽度的90%
# d.swipe_ext("right", box=(0, 0, 100, 100)) # 在 (0,0) -> (100, 100) 这个区域做滑动
# # 实践发现上滑或下滑的时候,从中点开始滑动成功率会高一些
# d.swipe_ext("up", scale=0.8) # 代码会vkk
#
# # # 上翻、下翻、左翻、右翻
# # # 还可以使用Direction作为参数
# from uiautomator2 import Direction
#
# # d.swipe_ext(Direction.FORWARD) # 页面下翻, 等价于 d.swipe_ext("up"), 只是更好理解
# # d.swipe_ext(Direction.BACKWARD) # 页面上翻
# # d.swipe_ext(Direction.HORIZ_FORWARD) # 页面水平右翻
# d.swipe_ext(Direction.HORIZ_BACKWARD) # 页面水平左翻
# 俩点移动
# d.drag(sx, sy, ex, ey)
# d.drag(0.149, 0.553, 0.841, 0.56, 0.5) # swipe for 0.5s(default)
#
# 多点移动
# swipe from point(x0, y0) to point(x1, y1) then to point(x2, y2)
# time will speed 0.2s bwtween two points
# points = [(0.1, 0.1), (0.3, 0.3), (0.7, 0.8)]
# 可以封装一个随机的上下翻页的函数,后续使用
# import random
# points = [(random.random(), 0.1), (random.random(), 0.3), (random.random(), 0.8)]
# points.reverse()
# d.swipe_points(points, 0.2)
# 按住并拖动
# 这个接口属于比较底层的原始接口,感觉并不完善,不过凑合能用。注:这个地方并不支持百分比
# 默认 [将日历软件挪动位置]
# d.touch.down(154, 1075) # 模拟按下
# time.sleep(random.random()) # down 和 move 之间的延迟,自己控制
# d.touch.move(667, 1077) # 模拟移动
# d.touch.up(667, 1077) # 模拟抬起
# 百分比支持
# 默认 [将日历软件挪动位置]
# window_x,window_y = d.window_size()
# print("window_x,window_y",window_x,window_y)
# def xy_int(x_lv,y_lv):
# return int(window_x*x_lv),int(window_y*y_lv)
#
# d.touch.down(xy_int(0.149, 0.56)[0],xy_int(0.149, 0.56)[1]) # 模拟按下
# time.sleep(1 + random.random()) # down 和 move 之间的延迟,自己控制
# d.touch.move(xy_int(0.829, 0.568)[0],xy_int(0.829, 0.568)[1]) # 模拟移动
# d.touch.up(xy_int(0.829, 0.568)[0],xy_int(0.829, 0.568)[1]) # 模拟抬起
# d.set_orientation('l') # or "left"
# d.set_orientation("l") # or "left"
# d.set_orientation("r") # or "right"
# d.set_orientation("n") # or "natural"
# freeze rotation
# d.freeze_rotation()
# un-freeze rotation
# d.freeze_rotation(False)
# take screenshot and save to a file on the computer, require Android>=4.2.
# 把截图并保存到一个文件在电脑上,需要Android > = 4.2。
# d.screenshot("home.jpg")
# 手机截图到python image
# get PIL.Image formatted images. Naturally, you need pillow installed first
# image = d.screenshot() # default format="pillow"
# image.save("home.jpg") # or home.png. Currently, only png and jpg are supported
# # get opencv formatted images. Naturally, you need numpy and cv2 installed first
# import cv2
# image = d.screenshot(format='opencv')
# cv2.imwrite('home.jpg', image)
#
# # get raw jpeg data
# imagebin = d.screenshot(format='raw')
# open("some.jpg", "wb").write(imagebin)
# 打开通知或快速设置
# d.open_notification()
# d.open_quick_settings()

 11.选择器

 这里可以结合weditor。

查看代码
 import json
import uiautomator2 as u2
import time,random
# 使用文档:https://github.com/zhaojiafu/uiautomator2#installation
# 可以通过ip、wifiadb、USB devices链接
d = u2.connect('192.168.61.187:5555') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
# 1、启动app
result = d.app_start("com.xingin.xhs")
print("result",result)
time.sleep(random.uniform(3,10))
# Selector supports below parameters. Refer to UiSelector Java doc for detailed information.
# http://developer.android.com/tools/help/uiautomator/UiSelector.html
# text, textContains, textMatches, textStartsWith
# className, classNameMatches
# description, descriptionContains, descriptionMatches, descriptionStartsWith
# checkable, checked, clickable, longClickable
# scrollable, enabled,focusable, focused, selected
# packageName, packageNameMatches
# resourceId, resourceIdMatches
# index, instance
# 2、点击搜索
# Select the object with text 'Clock' and its className is 'android.widget.TextView'
d(resourceId="com.xingin.xhs:id/b4r").click()
time.sleep(random.uniform(1,5))
# 3、输入内容
d(resourceId="com.xingin.xhs:id/b67").clear_text()
uid = "chenger261"
d(resourceId="com.xingin.xhs:id/b67").send_keys(uid)
time.sleep(random.uniform(1,5))
d.press("enter")
# 4、选择用户
d(text="用户").click()
time.sleep(random.uniform(1,5))
# 5、选择对的用户
user = d(resourceId="com.xingin.xhs:id/b6w", textContains=uid)
if user:
    print("user",user.info)
    user.click()
    time.sleep(random.uniform(1, 5))
    # 循环滑动
else:
    print("没有获取到用户")
time.sleep(random.uniform(10))
# 跑完记得关闭app
d.app_stop_all()

  12.获取页面的【类似于web的html】

  d.dump_hierarchy()函数。

查看代码
 # 获取页面的html【安卓的】
# get the UI hierarchy dump content (unicoded).
# xml = d.dump_hierarchy()
# with open('ret.html','w',encoding='utf-8') as file:
# file.write(xml)

  13.判断是否有下一页:

  对翻页前后的页面xml来对比是否一样,判断是否结束

查看代码
 import uiautomator2 as u2
import time,random
d = u2.connect("192.168.61.187:5555")
while True:
    # 获取每次滑动前页面下半部分的所有元素
    page_content = d.dump_hierarchy()[(len(d.dump_hierarchy()) // 2):]
    d.swipe_ext("up")
    time.sleep(random.uniform(0.5,3))
    # 获取每次滑动后页面下半部分的所有元素,并与上一次滑动前的页面元素对比,页面元素没有变化时跳出循环
    new_page_content = d.dump_hierarchy()[(len(d.dump_hierarchy()) // 2):]
    if new_page_content == page_content:
        break
print("swipe end")

注:以上总结都是适用于Android端的运行场景!

posted on 2023-09-06 10:53  彭泡芙  阅读(1597)  评论(1编辑  收藏  举报