1. 前言
上一篇推文利用一个在图片范围内实现随机坐标点击的例子,去教会大家如何将自己想要的效果实现出来,受到大家的热情反响,在我们官方讨论群中,还有大佬对我们的示例代码进行优化改进,做了很多合理的函数封装,以及减少了示例脚本内的二次查找等问题;我们也征得大佬同意,将他的代码与大家分享一下~(大佬来自Airtest官方讨论3群-Moty)
2. 代码分享
Moty同学是通过在本地python环境安装Airtest库去进行Airtest自动化脚本编写的,同时该脚本在AirtestIDE上是可以完美适配运行的。所以大家在编写自动化脚本的时候,可以有多重选择;但是AirtestIDE在代码编写上也有很多方便大家的小设计小巧思,大家也可以多多使用我们的AirtestIDE啊~
废话不多说,我们先来看看Moty同学代码的运行情况,可以看到通过生成随机坐标的形式,点击图片上的任意点,这里用计算器去具象化,可以看到每次随机坐标可以点击不同数字或者数字的不同位置,每次运行都可以获得随机的数字序列。
看起来很厉害的样子,我们应该这么去实现呢,让我们来看看Moty同学的代码吧~
# -*- encoding=utf8 -*- __author__ = "Moty" from airtest.core.api import * from airtest.cli.parser import cli_setup from airtest.core.error import * from airtest.core.settings import Settings as ST import random """ 获取模板匹配的目标区域的矩形 这一部分实现参考 cv.py 中 loop_find 部分 : param : tpl 模板 : param : intervalfunc 没有合适匹配时的回调函数 : return 最佳匹配的矩形区域(x1,y1,x2,y2) """ def rectangle(tpl,intervalfunc=None): G.LOGGING.info("Try finding: %s", tpl) start_time = time.time() while True: screen = G.DEVICE.snapshot(filename=None, quality=ST.SNAPSHOT_QUALITY) if screen is None: # 如果截图为空,则可能是屏幕锁定了 G.LOGGING.warning("Screen is None, may be locked") else: match_result = tpl._cv_match(screen) if match_result: try_log_screen(screen) # 这里 rect 得到的是 4个坐标点 取出左上右下角 得到(x1,y1,x2,y2) 元组 rect = match_result.get("rectangle") if rect is not None: return (round(rect[0][0]) , round(rect[0][1]) , round(rect[2][0]) , round(rect[2][1])) if intervalfunc is not None: intervalfunc() # 超时则raise,未超时则进行下次循环: if (time.time() - start_time) > ST.FIND_TIMEOUT: try_log_screen(screen) # 如果超时,则抛出异常 raise TargetNotFoundError('Picture %s not found in screen' % tpl) else: time.sleep(0.5) """ param : rect : 矩形区域 或模板 return : 区域内的随机坐标 """ # 获取矩形区域内的随机坐标 def random_point(rect): # 如果传入的是图片,则获取图片匹配的矩形区域 if isinstance(rect, Template): x1, y1, x2, y2 = rectangle(rect) else: x1, y1, x2, y2 = rect # 在矩形区域内随机生成一个坐标点 x = random.randint(x1, x2) y = random.randint(y1, y2) return x, y """ 在 矩形范围内 随机点击 param : v : 目标区域 or 模板 or 坐标点(兼容touch) param : times : 点击次数 return :最终点击的点的坐标 """ @logwrap def random_touch_in_area(v, times=1, **kwargs): if isinstance(v, Template) or (isinstance(v, tuple) and len(v) == 4): pos = random_point(v) else: try_log_screen() pos = v # 在目标区域内随机点击 for _ in range(times): G.DEVICE.touch(pos, **kwargs) time.sleep(0.05) delay_after_operation() return pos if __name__ == '__main__': # 如果没有通过命令行连接设备,则使用该连接命令,若使用IDE运行则可忽略这段代码,不用写上 if not cli_setup(): auto_setup(__file__, logdir=None, devices=["android:///",]) # 录制图片 tpl = Template(r"tpl1697636105500.png", record_pos=(0.243, -0.165), resolution=(1080, 2280)) # 获取模板匹配的目标区域的矩形 result = rectangle(tpl) print(f"图片所在矩形区域 {result}") # 在目标区域内随机点击 for i in range(10): p = random_touch_in_area(tpl) print(f"第 {i+1:02d} 次点击坐标 {p}") sleep(1)
可以看出来,在编写代码的时候,Moty同学将每一个步骤进行函数封装后,可以减少二次查找的次数以及代码冗余,Moty同学的编写思路很值得我们学习~
3.小结
最后,希望同学们在学习以及使用Airtest的时候,可以先学习方法,掌握代码编写技巧后,对自己的脚本可以进行优化再优化,从而实现代码收益最大化。同时,我们也鼓励大家在学习我们的官方教程脚本的时候,进行优化再创作,也可以到我们官方Q群进行投稿噢~
官方Q群:目前1、2、3群已满,大家可以加入4群(117973773)。
这里附上我们官方教程文档的网址,欢迎同学们查阅哦:airtest.doc.io.netease.com/ 。