本文主要是介绍app 自动化工具uiautomator2 + app页面分析工具weditor的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、踩坑经历
- 习惯性思维
- 转折--发现新大陆 weditor
- 二、学习weditor
- 1、安装和打开:
- 2、简单使用
- 1)、链接手机调试
- 2)、分析页面元素
- 3)、引发思考--找到可以代替appium的模块uiautomator2
- 三、学习uiautomator2的简单使用:
- 1、安装:
- 2、连接手机:
- 3、启动一个app--`app_start`函数
- 4、停用一个app
- 5、获取一个app信息
- 6、等待app运行:
- 7、 文件传输
- 8、检测设备状态【测试感觉没有什么用,好像后期去掉了】
- 9、执行shell命令:
- 10、各种设备信息
- 11、滑动、点击等动作
- 12、选择器:
- 13、录屏:
- 14、获取页面的【类似于web的html】
- 15、判断是否有下一页:
- 总结:
- 参考:
一、踩坑经历
习惯性思维
这个确实菜踩了不少的坑,刚开始我是打算使用appium,和安卓的sdk的页面分析工具,uiautomatorviewer和monitor来做。
这个是受惯性思维吧,因为之前学习appium的使用,就是这样搞的,但是已经有将近俩年没有再碰了,不过windos端,我还是在把环境搞好了,但是公司办公使用是mac系统,导致我安装好安装的SDK也无法使用uiautomatorviewer和monitor,我把JDK也都卸载重装了好几遍。。。。
mac大概搞了一天,实在头大。。。
window前一天在家又搞到凌晨三点。。。吐血
转折–发现新大陆 weditor
就在我想放弃使用mac来搞这个的时候,突然在搜索monitor问题的时候,在一个论坛有个评论说建议使用weditor,顿时发现这个应该能代替我想弄的uiautomatorviewer和monitor。
然后开始搜索weditor
搜到项目地址
https://github.com/alibaba/web-editor
发现在阿里巴巴项目下,
然后搜到一篇文章,开启了学习weditor,放弃安卓SDK的uiautomatorviewer和monitor来定位分析页面。
https://www.cnblogs.com/RuguoCheng/p/10457637.html
二、学习weditor
1、安装和打开:
安装:
pip3 install -U weditor
使用:
python -m weditor
浏览器访问:
http://localhost:17310/
发现是真的好用呀,不用考虑系统。是mac还是window,直接浏览器打开分析。
简直爱的不行
2、简单使用
1)、链接手机调试
mac终端或者win cmd执行:
python -m weditor
一般默认会自动打开系统默认的浏览器,如果不打开,自己打开:
访问:
http://localhost:17310/
然后把手机打开usb调试:
点击连接connect并点击 Dump Hierarchy,就会显示手机页面。
如下图:
是不是很棒
2)、分析页面元素
点击一个你想点击的元素:
就会出现,如下图:
className 就和html页面的class属性一样。
resourceId 就和html页面的id属性一样。
d(resourceId=“com.xingin.xhs:id/bn_”) 就是选择器的用法。
由于之前学习了lua脚本,定位安卓的用法,所以这个看下我就懂了。
3)、引发思考–找到可以代替appium的模块uiautomator2
找到的灵感来自于俩个思路:
1、上一步页面显示的d(resourceId="com.xingin.xhs:id/bn_")
中的d
是什么东东?
当然,如果是我最初的方法,目前已经解决了,当时突然想知道d
是什么
2、
进入weditor的项目页面:
https://github.com/alibaba/web-editor
看的有俩个依赖:uiautomator2和facebook-wda
然后进入uiautomator2页面看看
https://github.com/openatx/uiautomator2
看到了下面这段:
我的理解就是和appium差不多。
UiAutomator是Google提供的用来做安卓自动化测试的一个Java库,基于Accessibility服务。功能很强,可以对第三方App进行测试,获取屏幕上任意一个APP的任意一个控件属性,并对其进行任意操作,但有两个缺点:1. 测试脚本只能使用Java语言 2. 测试脚本要打包成jar或者apk包上传到设备上才能运行。
我们希望测试逻辑能够用Python编写,能够在电脑上运行的时候就控制手机。这里要非常感谢 Xiaocong He
(@xiaocong),他将这个想法实现了出来(见xiaocong/uiautomator),原理是在手机上运行了一个http
rpc服务,将uiautomator中的功能开放出来,然后再将这些http接口封装成Python库。
因为xiaocong/uiautomator这个库,已经很久不见更新。所以我们直接fork了一个版本,为了方便做区分我们就在后面加了个2
openatx/uiautomator2
往下在看看:
发现:
看到了d
,原来页面的d
就是使用这个项目。
开始学习下uiautomator2
三、学习uiautomator2的简单使用:
1、安装:
直接pip安装即可
pip install --upgrade --pre uiautomator2
2、连接手机:
有三种方式,一种是常用的usb,一种是wifiadb【可以借助软件】,还有一种直接局域网的ip地址。
Wi-Fiadb软件,下面是我自己收藏的软件,可以下载使用
app抓包小黄鸟、xposed、wifiadb、等工具软件
https://wwa.lanzoui.com/b00ullejg
密码:ackl
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
函数
需要传入包名
可以通过weditor获取。
比如:随便进入一个软件,点击一个位置就可以拿到包名。
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")
输出小红书app信息:
{"packageName": "com.xingin.xhs","mainActivity": "com.xingin.xhs.activity.SplashActivity","label": "小紅書","versionName": "6.25.0","versionCode": 6250099,"size": 63197480
}
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差不多的功能。
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))# 外部往手机端推送
# 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、检测设备状态【测试感觉没有什么用,好像后期去掉了】
DeprecationWarning: Call to deprecated method healthcheck. (method: healthcheck is useless now) – Deprecated since version 3.0.0.
测试感觉没有什么用
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')
d = u2.connect('87d1294c') # alias for u2.connect_wifi('10.0.0.1')
print(json.dumps(d.info,ensure_ascii=False))
# healthcheck = d.healthcheck()
healthcheck = d.healthcheck()
print("healthcheck",healthcheck)
9、执行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:breakprint("Read:", line.decode('utf-8'))
finally:r.close() # this method must be called
10、各种设备信息
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)
11、滑动、点击等动作
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()
12、选择器:
这里可以结合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()
13、录屏:
这个效果不是特别好,我用到的可能性不大,如果需要可以用下。
放在自动化控制app脚本前后录屏。
# pip3 install -U "uiautomator2[image]" -i https://pypi.doubanio.com/simple
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))d.screenrecord('output.mp4')
print("开始录屏")
time.sleep(10)
# or do something elseprint("结束")
d.screenrecord.stop() # 停止录制后,output.mp4文件才能打开
14、获取页面的【类似于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)
15、判断是否有下一页:
对翻页前后的页面xml来对比是否一样,判断是否结束。
import uiautomator2 as u2
import time,randomd = 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:breakprint("swipe end")
总结:
https://github.com/openatx/facebook-wda
这个好像是ios手机的模块,我没有苹果手机,暂时没有仔细看。感兴趣的自己研究试试吧。
经过学习下uiautomator2和weditor,发现uiautomator2可以代替appium,俩者可以达到一样的效果。
weditor的页面分析做的确实很棒,比安卓的SDK里面的uiautomatorviewer和monitor俩个功能来查看页面强很多,而且环境不用考虑mac和window各弄很久。
注意我mac弄了一天也没有弄好,用了这个就决定放弃安卓的SDK了。
参考:
https://www.cnblogs.com/RuguoCheng/p/10457637.html
https://github.com/alibaba/web-editor
https://github.com/openatx/uiautomator2
https://github.com/openatx/facebook-wda
这篇关于app 自动化工具uiautomator2 + app页面分析工具weditor的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!