提示:以下是本篇文章正文内容
1.引入库import os import time import random import datetime import uiautomator2 as ut2、检测连接手机(列表是用来做多线程执行…还未实现)
devices = [] # 检测是否连接手机 try: for dName_ in os.popen("adb devices"): if "t" in dName_: if dName_.find("emulator") < 0: devices.append(dName_.split("t")[0]) devices.sort(cmp=None, key=None, reverse=False) except: pass3、报警提示(该位置使用的是飞书群机器人报警,也可以使用其他方式,例如:钉钉、邮件、短信)
if devices == []: msg = 'Android手机 导致无法找到devices 进行启动Android自动化脚本。' send_FeiShu("无法连接", msg) exit()4、录制case执行视频(直接用当前时间做视频名称,判断有没有video文件夹)
today = (datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S') VideoName = f"case_{today}" if not os.path.exists("video"): os.makedirs('video') VideoPath = 'video' device.screenrecord(VideoPath + "/" + VideoName + ".mp4")5、查找应用(获取当前页面所有的文案,判断程序有没有在,没有就在下一屏找,直到找到并打开)
while True: device.press("home") device.press("home") text_list = [ele.text for ele in device.xpath('//android.widget.TextView').all()] if "XXX" not in text_list: device.swipe_ext('left', scale=0.9) else: device(text="XXX").click() time.sleep(5) try: device(resourceId="com.xxxxx.xxxxx:id/iv_dialog_active_close").click() except: print("不存在弹窗") break6、text文档(编写执行case,格式如下)
例如:1、xx>xxx.xxxxx.xxxxx - xx>xxx.xxxxx.xxxxx
当中:“1、”、“>”、" - " 为解析使用
1、首页>com.xxxxx.xxxxx:id/button_bar_home_img - 直播电商>xxx.xxxxx.xxxxx:id/button_bar_streaming_img - 达人>xxx.xxxxx.xxxxx:id/button_bar_ranking_img - 社区>xxx.xxxxx.xxxxx:id/button_bar_commodity_img - 我的>xxx.xxxxx.xxxxx:id/button_bar_user_img 2、实时直播>xpath('//*[@resource-id="com.xxxxx.xxxxx:id/rlHomeFunction"]/android.view.ViewGroup[1]/android.widget.ImageView[1]') - 退出页面登录>com.xxxxx.xxxxx/ivPhoneLoginBack 3、我的>com.xxxxx.xxxxx:id/button_bar_user_img - 登录 - 首页>com.xxxxx.xxxxx:id/button_bar_home_img 4、直播引流>com.xxxxx.xxxxx:id/tv_live_business_live_drainage - 上滑(下滑)7、解析case(读取case文档,进行解析)
# 读取文档,获取case with open('ExecuteCodeAndroid.text', 'r', encoding='UTF-8') as code_find: # 解析case code_list = [code_i.split('、')[1].replace('n', '').split(' - ') for code_i in code_find.readlines()] for i in range(len(code_list)): for code_list_i in code_list[i]:8、校验弹窗(获取当前页面所有文案,校验有没有关键词,有就进行指定点击)
# 获取当前页面文案,判断是否有弹窗 Tips = [elem.text for elem in device.xpath('//android.widget.TextView').all()] if "个人信息保护指引" in Tips: device(resourceId="com.xxxxx.xxxxx:id/tv_dialog_agreement_confirm").click() device.swipe_ext("left", 0.6) device.swipe_ext("left", 0.6) device(resourceId="com.xxxxx.xxxxx:id/btn_item_welcome").click() elif "好像哪里出错了" in Tips: device.xpath('//*[@text="返回"]').click() elif "信息走失啦" in Tips: device.xpath('//*[@text="刷新"]').click() elif "暂无数据" in Tips: device.xpath('//*[@text="稍后再试"]').click() elif "访问过于频繁" in Tips: device.xpath('//*[@text="稍后再试"]').click() elif "您当前账号登录" in Tips: device.xpath('//*[@text="取消"]').click()9、执行(详细执行功能点击操作)
# 解析后长度大于等于 2 的时候 if len(code_list_i.split('>')) >= 2: if 'xpath' in code_list_i.split('>')[1]: device.xpath(f"""{code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]}""").click() else: if ", text=" in code_list_i.split('>')[1]: resourceId_ = code_list_i.split('>')[1].split(', text=')[0] text_ = code_list_i.split('>')[1].split(', text=')[1].replace('"', '') device(resourceId=f"{resourceId_}", text=f"{text_}").click() else: if "text" in code_list_i.split(">")[1]: text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0] device(text=f"{text_name}").click() else: device(resourceId=f"{code_list_i.split('>')[1]}").click() # 小于 2 elif code_list_i.split('>')[0] == "登录": AndroidLogin() elif code_list_i.split('>')[0] == "退出登录": AndroidLogout() elif code_list_i.split(">")[0] == "输入": device(resourceId="com.xxxxx.xxxxx:id/etSearchEdit").set_text(InputGbk2312()) device.send_action('search') elif code_list_i.split('>')[0] == "上滑": Slide_up() elif code_list_i.split('>')[0] == "下拉": Slide_down()10、全部代码
import os import time import random import datetime import uiautomator2 as ut from call_the_police import send_FeiShu # 飞书报警 while True: devices = [] # 检测是否连接手机 try: for dName_ in os.popen("adb devices"): if "t" in dName_: if dName_.find("emulator") < 0: devices.append(dName_.split("t")[0]) devices.sort(cmp=None, key=None, reverse=False) except: pass if devices == []: msg = 'Android手机 导致无法找到devices 进行启动Android自动化脚本。' send_FeiShu("无法连接", msg) exit() else: device = ut.connect_usb(devices[0]) # 录制视频 today = (datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S') VideoName = f"case_{today}" if not os.path.exists("video"): os.makedirs('video') VideoPath = 'video' device.screenrecord(VideoPath + "/" + VideoName + ".mp4") # 手机中查找 相关应用 while True: device.press("home") device.press("home") text_list = [ele.text for ele in device.xpath('//android.widget.TextView').all()] if "抖查查" not in text_list: device.swipe_ext('left', scale=0.9) else: device(text="抖查查").click() time.sleep(5) try: device(resourceId="com.xxxxx.xxxxx:id/iv_dialog_active_close").click() except: print("不存在弹窗") break # 登录 def AndroidLogin(): try: device.xpath( '//*[@resource-id="com.xxxxx.xxxxx:id/ll_user_top"]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]').click() except: print('非"我的"页面进行登录') device(text="密码登录").click() device(resourceId="com.xxxxx.xxxxx:id/cb").click() device(text="请输入手机号").set_text("18730301074") device(text="请输入密码").set_text("ceshi123") device(text="登录").click() # 退出登录 def AndroidLogout(): device(resourceId="com.xxxxx.xxxxx:id/tv_user_setting").click() device(resourceId="com.xxxxx.xxxxx:id/btnLogout").click() device(resourceId="com.xxxxx.xxxxx:id/tv_logout_confirm").click() # 随机输入 1 个字 def InputGbk2312(): head = random.randint(0xb0, 0xf7) body = random.randint(0xa1, 0xfe) val = f'{head:x}{body:x}' str = bytes.fromhex(val).decode('gb2312') return str # 上滑 def Slide_up(): device.swipe_ext("up", 0.6) # 下拉 def Slide_down(): device.swipe_ext("down", 0.6) # 读取文档,获取case with open('ExecuteCodeAndroid.text', 'r', encoding='UTF-8') as code_find: # 解析case code_list = [code_i.split('、')[1].replace('n', '').split(' - ') for code_i in code_find.readlines()] for i in range(len(code_list)): for code_list_i in code_list[i]: # 获取当前页面文案,判断是否有弹窗 Tips = [elem.text for elem in device.xpath('//android.widget.TextView').all()] if "个人信息保护指引" in Tips: device(resourceId="com.xxxxx.xxxxx:id/tv_dialog_agreement_confirm").click() device.swipe_ext("left", 0.6) device.swipe_ext("left", 0.6) device(resourceId="com.xxxxx.xxxxx:id/btn_item_welcome").click() elif "好像哪里出错了" in Tips: device.xpath('//*[@text="返回"]').click() elif "信息走失啦" in Tips: device.xpath('//*[@text="刷新"]').click() elif "暂无数据" in Tips: device.xpath('//*[@text="稍后再试"]').click() elif "访问过于频繁" in Tips: device.xpath('//*[@text="稍后再试"]').click() elif "您当前账号登录" in Tips: device.xpath('//*[@text="取消"]').click() # 解析后长度大于等于 2 的时候 if len(code_list_i.split('>')) >= 2: if 'xpath' in code_list_i.split('>')[1]: device.xpath(f"""{code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]}""").click() else: if ", text=" in code_list_i.split('>')[1]: resourceId_ = code_list_i.split('>')[1].split(', text=')[0] text_ = code_list_i.split('>')[1].split(', text=')[1].replace('"', '') device(resourceId=f"{resourceId_}", text=f"{text_}").click() else: if "text" in code_list_i.split(">")[1]: text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0] device(text=f"{text_name}").click() else: device(resourceId=f"{code_list_i.split('>')[1]}").click() # 小于 2 elif code_list_i.split('>')[0] == "登录": AndroidLogin() elif code_list_i.split('>')[0] == "退出登录": AndroidLogout() elif code_list_i.split(">")[0] == "输入": device(resourceId="com.xxxxx.xxxxx:id/etSearchEdit").set_text(InputGbk2312()) device.send_action('search') elif code_list_i.split('>')[0] == "上滑": Slide_up() elif code_list_i.split('>')[0] == "下拉": Slide_down() # list_data = [elem.text for elem in device.xpath('//android.widget.TextView').all()] # if "暂无相关数据" in list_data: # msg = f"case: {i + 1}" # send_FeiShu("无数据", msg) # 增加钉钉或飞书报警 # 结束录制 device.screenrecord.stop() break总结
例如:以上就是今天要讲的内容,本文仅仅只是对于uiautomator2+Android+python的使用,而uiautomator2依旧有很多待发现的内容,等待我们发现。
近期会将ios的自动化同步到此,敬请期待哦!