首页 > 其他分享 >如何用Airtest实现在图片范围内随机点击

如何用Airtest实现在图片范围内随机点击

时间:2024-02-25 18:01:01浏览次数:20  
标签:随机 pos 点击 坐标 Airtest 图片

1. 前言

前几天有个新手同学在Airtest官群里问了这样一个问题:
我是新手,在图片范围内随机点击 ,用Airtest怎么实现?代码?
那我们就以这个问题为例,浅浅聊一下,怎么把需求转化成我们的Airtest代码。

2. 了解Airtest

首先新手同学对Airtest要有以下几点认知:
  • ① Airtest是一个图像识别框架,它能在屏幕上用图像识别来找到想操作的位置并点击,所以Airtest本质上点击的是目标图片的坐标,默认是中心点
  • ② Airtest是python第三方库,除了Airtest本身的接口之外,我们随时可以import python的标准库或者其它第三方库,一起使用

3. 分析需求,转化成代码

1)查文档,找现成方法
有了以上2点认知后,我们再回到需求,“在图片范围内随机点击”,第一步我们要做的就是查询官方教程文档,看下有没有现成的方法可以使用:
  • ① 一般情况下,Airtest都是点击图片中心位置,不知道有没有点击图片内其它坐标的方法
  • ② 随机点击,怎么实现在图片内随机点击这个行为,不知道Airtest有没有随机点的方法
当我们查阅Airtest的教程文档之后,发现Airtest确实提供了点击图片内非中心坐标的方法,就是指定target_pos,但是只能点击图片内的9个点:

 

这里似乎并不太符合在图片范围内随机点的需求。随后我们又查询了文档,发现Airtest也没有提供随机点击的方法。
2)分析需求,自己实现
那么我们到这里就需要进入到第二步,分析需求,看看需求都有哪些难点需要我们实现:
  • ① 在图片范围内点击,那意味着在整个图片的坐标范围内点击,那我们怎么拿到整个图片的坐标范围?
  • ② 怎么点击一个随机的坐标?
针对第一个难点,其实我们分别拿到目标图片x、y坐标的最小、最大值,就能确认坐标范围了。再进一步思考,一张图片x最小值是图片的最左侧,最大值是图片最右侧;y最小值是图片最上方,最大值是图片最下方;那就意味着,我们只要拿到图片左上角和右下角的坐标,就能完全确认目标图片x、y坐标的最小、最大值,进而确认图片坐标范围。第一个难点解决后,再来看第二个难点,随机点,这里就要借助python的标准库random了,能帮助我们生成一个随机数的函数。
3)将思考转化成代码
最后一步就是将我们刚才分析需求,得到的思路,转化成代码:

图片

# -*- encoding=utf8 -*-
__author__ = "AirtestProject"

from airtest.core.api import *
import random

auto_setup(__file__)

# 定义函数,得到目标图片的坐标范围
def pos_range():
if exists(Template(r"tpl1697515204054.png", target_pos=1, record_pos=(-0.16, 0.154), resolution=(2960, 1440))):
up_pos = exists(Template(r"tpl1697515204054.png", target_pos=1, record_pos=(-0.16, 0.154), resolution=(2960, 1440))) # 利用target_pos=0,拿到目标图片左上角的坐标
down_pos = exists(Template(r"tpl1697515204054.png", target_pos=9, record_pos=(-0.16, 0.154), resolution=(2960, 1440))) # 利用target_pos=9,拿到目标图片右下角的坐标
x = (int(up_pos[0]),int(down_pos[0])) # 拿到图片x坐标的范围
y = (int(up_pos[1]),int(down_pos[1])) # 拿到图片y坐标的范围
return x,y
else:
print("目标图片不存在")

# 分别拿到图片x坐标与y坐标的范围值
pos_r = pos_range()
x = pos_r[0]
y = pos_r[1]

# 在x、y的坐标范围内生成随机数
x_range = random.randint(x[0],x[1])
y_range = random.randint(y[0],y[1])

# 点击图片范围内任意坐标
touch([x_range,y_range])

4. 优化版

      以上是简单的一个实现,效率不是最优。下面介绍一个更优的实现方案:      Moty同学是通过在本地python环境安装Airtest库去进行Airtest自动化脚本编写的,同时该脚本在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同学的编写思路很值得我们学习~

5.小结

最后,希望同学们在学习以及使用Airtest的时候,可以先学习方法,掌握代码编写技巧后,对自己的脚本可以进行优化再优化,从而实现代码收益最大化。

---------------------------------------------------------------------------------

关注微信公众号即可在手机上查阅,并可接收更多测试分享~

标签:随机,pos,点击,坐标,Airtest,图片
From: https://www.cnblogs.com/songzhenhua/p/18032676

相关文章

  • Airtest:各平台的剪切板功能汇总
    1.前言一直以来,大家都还挺关注 Airtest是否有剪切板功能 的。从Airtest1.3.1版本起,我们新增了Android、iOS设备的剪切板功能,自此,3大平台的剪切板功能就齐全啦。正好趁这个机会,我们给各大平台的剪切板功能做个合集,方便同学们查阅使用~2.Android设备的剪切板功能Android设备的......
  • pytest简易教程(30):pytest常用插件 - 随机执行(pytest-random-order)
     pytest简易教程汇总,详见:https://www.cnblogs.com/uncleyong/p/17982846应用场景用来验证用例在随机(无序)执行时是否正常 插件安装pipinstallpytest-random-order 使用方式加参数:--random-order 示例#!/usr/bin/envpython#-*-coding:utf-8-*-#@Author......
  • 随机旋转岩石工具
    思路:制作一个石头模型并对其碰撞进行自动凸包,放入蓝图中,通过蓝图中的构造脚本进行随机旋转,即可实现石块放置时的旋转效果;演示操作1.创建石头模型使用BSP工具进行顶点编辑添加材质后转成静态网格体对模型进行自动凸包碰撞2.蓝图中控制石块的随机旋转和缩放为了方便控制缩......
  • R语言逻辑回归(Logistic Regression)、回归决策树、随机森林信用卡违约分析信贷数据集
    原文链接:http://tecdat.cn/?p=23344最近我们被客户要求撰写关于信用卡违约分析的研究报告,包括一些图形和统计输出。本文中我们介绍了决策树和随机森林的概念,并在R语言中用逻辑回归、回归决策树、随机森林进行信用卡违约数据分析决策树是由节点和分支组成的简单树状结构。根据每......
  • 测试也能开发 - 点击二级分类实现自动筛选功能
    写在前面怎么来诠释下现在的心情呢?算是比较复杂吧,我也想过关于自己个人问题的事,始终是无解的状态。35岁,变成了一个没有胆量、小心翼翼的年纪,甚至说慎重到说话都要反复思考的程度,先不说内耗问题了,真的就是负能量爆棚了,我有那么一阵极度怀疑自己丧失了和人沟通的能力。今天,我co......
  • 【更新公告】AirtestIDE更新至1.2.17版本
    1.前言本次更新为AirtestIDE、Airtest-Selenium库更新。AirtestIDE更新至1.2.17版本,AirtestIDE内置库Airtest更新为1.3.3.1版本,Poco更新为1.0.94版本,主要支持了selenium4.0以上版本,ADB更换为41版本,Airtest新增点击和滑动的相对坐标支持,Poco修复了1.0.93运行效率缓慢的问题等......
  • 在WPF的RichTextBox富文本中加入一个可点击的按钮
    <RichTextBox><local:MyFlowDocument><Paragraph><InlineUIContainer><ButtonContent="ClickMe!"Click="Button_Click"/>......
  • 2024.2.20闲话——luogu5021随机选取边的正确性
    推歌:生きる(feat.可不)——水野あつ这首歌听完之后接着转去咖喱乌冬了,歌词甚至能接上,没绷住。刚刚写证明中间把wxy的杯子碰倒洒键盘上了,抢救键盘的过程中碰到缝就有水,有点涩。但是这个键盘里面怎么这么脏啊?下面来证luogu5021在菊花树中以任何顺序选取边并采取贪心策略的......
  • input,type为number时隐藏点击按钮和限制输入最大最小值
    //隐藏点击按钮input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;}input[type='number']{-moz-appearance:textfield;}//解决输入中文后光标上移的问题.el-input__inner{line-height:1px!important;}//......
  • golang随机数源码分析及应用
    引言大家刚开始使用随机数的时候可能会这样写,但是他会产生一个问题,这是什么问题呢funcmain(){ fori:=0;i<10;i++{ rand.Seed(time.Now().Unix()) fmt.Println(rand.Intn(100)) }}发现打印出来的结果都是相同的让我们看看用代码分析为什么产生这个问题首......