04实战 – 边学边用

AffettoIris 2023-11-26 3,455 11/26

 

实战 - 商城自动签到

手动签到的流程:准备登录 -> 输入卡密 -> 滑块验证码 -> 登录成功 -> 签到。

项目目录介绍

04实战 - 边学边用

res文件夹即resources,资源文件夹。存放了img文件夹(图片)、ui文件夹和其他资源文件。__init.py__是默认的项目入口,build.as文件是项目依赖,你看上图,从第三行看起,是不是就是pip install opencv-contrib-python==4.1.2.30等命令。.as文件目测是AirScript的缩写。

签到自动化 - 常用api的使用

滑块验证码有点高级,需要opencv识别/基于超级鹰等识别api,略过了,但是对于多个账号批量签到自动化,肯定是不能略过,得自学的啦。

打开工具箱

点网页上"工具集"按钮:

04实战 - 边学边用

或者pycharm的AirScript Console的工具箱按钮:

04实战 - 边学边用

都能打开工具箱:

04实战 - 边学边用

我的模拟器不知道哪里没调好,网页端调用不了模拟器的屏幕(老师那边是可以调用模拟器的屏幕。),我选用平板。

点击工具箱里的“控件检索”,然后选中右下方"我的"按钮,可以查看到很多属性,例如是否可点击。控件的类型、路径等:

04实战 - 边学边用

如果手机上切换了界面,你再点击下“简单模式“ / ”复杂模式”即可刷新投屏:

04实战 - 边学边用

先通过控件类型粗筛

点击控件属性右边的“+”可以生成 根据该属性查找本页面中 所有/第一个 具有该属性的元素

04实战 - 边学边用

再通过控件某个地标性属性精确定位

上图的查找结果有多个,我就想精准定位到“我的”按钮,那就再点击"文本:我的"属性右边的"+",优化下查找语句:

04实战 - 边学边用

这次只查到一个节点。

值得说明的是,例如Selector().type("View").text("我的").find_all()语句,采用的都是模糊匹配,所以Selector().type("View")会查找到TextView和View类型控件,Selector().text("我的")会匹配到文本为"我的"、“我的钱包”等控件。

要想精确定位到只有一个结果,比较常用的地标性属性是路径、控件深度、是否可点击属性等。但是路径例如“/FrameLayout/FrameLayout/TextView”比较长,写出的代码长的出丑,你也不想看Selector().type("FrameLayout").path("/FrameLayout/FrameLayout/TextView").find_all()这么长的代码吧,所以尽量用其他书写较短的属性替代,Selector().type("FrameLayout").depth(3).find_all()这样就好看多了。

执行动作

我们不仅可以看到节点的属性,AirScript还提供了关系操作、动作操作:

04实战 - 边学边用

我现在想点击"我的"节点,就点动作 - click右边的"+",优化表达式为Selector().type("TextView").text("我的").click().find_all()

执行上述语句,在手机上,你选中的控件会被点击,从而触发相应后果。不过我这里没有跳转页面,细究原因,发现是选中的控件是不可点击属性。

获取所选控件的父级/孩子/兄弟控件

04实战 - 边学边用

看上图,绿色小框是我上述代码选中的控件,是不可点击的,绿色大框才是可点击的控件。我已唯一性选中绿色小框,那就查找它的父级控件吧。

04实战 - 边学边用

为什么填1?:

04实战 - 边学边用

看图,填1表示选中"我的"控件的一级父辈控件(图中绿色),填2表示选中"我的"控件的二级父辈控件(图中黄色),以此类推。

现在我们得到了想要的Selector().type("Textview").text("我的").parent(1).click().find_all()语句,复制到pycharm中,同步到手机上,然后执行即可。

关系函数的参数

AirScript提供了获取孩子、兄弟、父辈控件的三种关系函数,以兄弟关系函数Node().brother(*n)为例,演示参数的写法。查看官方文档可知:

04实战 - 边学边用

模拟人的操作,避免被检测

Selector().type("Textview").text("我的").parent(1).click().find_all()  # 点击“我的”按钮进入“我的”界面 
Selector().type("Textview").text("签到").click().find_all()  # 点击“签到”按钮进入“签到”界面 

直接执行上述代码,机器刚点完“我的”按钮就立马点“签到”按钮,反人类,正常人不点这么快的,在一些app上会检测你的这些反人类操作(我记得淘宝、王者还有截屏来检测的做法)。所以我们加入点时间间隔:

import time

Selector().type("Textview").text("我的").parent(1).click().find_all()  # 点击“我的”按钮进入“我的”界面 
time.sleep(1)
Selector().type("Textview").text("签到").click().find_all()  # 点击“签到”按钮进入“签到”界面 

判断某控件是否存在

例如"我的"按钮的查找路径是Selector().type("Textview").text("我的").find_all(),当能找到这个按钮,就点击按钮,如果因从app退回到桌面而找不到按钮,就不点击,避免脚本报错而终止运行:

if Selector().type("Textview").text("我的").find_all() == None:
    Selector().type("Textview").text("我的").click().find_all()

python获取某控件的某属性值

有个控件能被Selector().type("FrameLayout").depth(3).find_all()唯一地定位到,我们打印下

control = Selector().type("FrameLayout").depth(3).find_all()
print(control)

#打印结果是一个数组,为jarray('Lairscript/node/Node;')([<airscript.node.Node 'Node{id='com.android.systemui:id/wifi_combo', text='null', type='FrameLayout', desc='WLAN 信号满格。', hintText='null', packageName='com.android.systemui', path='/FrameLayout/FrameLayout/FrameLayout', rect=Rect(1430, 7 - 1483, 53), childCount=0, inputType=0, maxTextLength=-1, drawingOrder=33, depth=3, clickable=false, checkable=false, checked=false, editable=false, enabled=true, visible=true, dismissable=false, focusable=false, focused=false, heading=false, longClickable=false, childs=[]}'>])

print(len(control)) # 数组长度1

数组长度为1,其实如果Selector().type("FrameLayout").depth(3).find_all()能定位到两个控件,数组长度则为2,所以数组里每个元素是一个控件你可以用python的数组索引来定位控件。

control = Selector().type("FrameLayout").depth(3).find_all()
print(control[0])
# Node{id='com.android.systemui:id/wifi_combo', text='null', type='FrameLayout', desc='WLAN 信号满格。', hintText='null', packageName='com.android.systemui', path='/FrameLayout/FrameLayout/FrameLayout', rect=Rect(1430, 7 - 1483, 53), childCount=0, inputType=0, maxTextLength=-1, drawingOrder=33, depth=3, clickable=false, checkable=false, checked=false, editable=false, enabled=true, visible=true, dismissable=false, focusable=false, focused=false, heading=false, longClickable=false, childs=[]}

print(control[0].desc)
# 获取到控件的属性值:WLAN 信号满格。

获取find_all()的第N个控件

例如Selector(2).type("LinearLayout").find_all()的查询结果有好几个:

04实战 - 边学边用

我想要第二个,有没有快速的方法嘞?:

  • 没有find_all(2)这种语法,只有find()和find_all()

  • 你可以导入到python里,通过python的数组的索引获取。舒服了python代码,但是没舒服在网页上的线上调试。

    control = Selector(2).type("LinearLayout").find_all()
    print(control[1])
  • 多加点限制条件,控件深度、路径啥的加上,精确定位。

  • 通过目标附近的其他易唯一性定位的元素。例如Selector(2).type("View").find_all()只有一个结果,记为A,你要找的元素记为B,A和B是上下相邻的兄弟关系,于是你可以写代码为A.brother(-0.1)来定位到B。

判断图色

有个需求:

04实战 - 边学边用

当我们已经勾选单选框时,不再点击,否则点击,而该控件,勾选前后没有任何路径、属性等变化。这时需要借助图色判断。

点击工具箱 -> 图色检索 -> 找图:

04实战 - 边学边用

如下图,你可以截图、看到已有截图、删除某张截图:

04实战 - 边学边用

点击多点找色栏,然后把鼠标放在投屏上,直到出现原形放大镜。按下键盘上的1~9九个数字键,例如按下1键,网页会把鼠标所在点的坐标和色值记录在第一行:

04实战 - 边学边用

注意到"偏色 : #0505",就是色值偏差。因为不同手机型号的绘图API不一样,都是画红色,画出的红色的RGB值略有不同,一般而言"偏色 : #0505"就够了,色值不会出现太大的偏差。

现在我们有了代码FindColors('1532,1567,#FB4774|1524,1567,#F75279|1540,1591,#FB2E58').find_all()并且允许"偏色 : #0505",点击”查找全部“

04实战 - 边学边用

注意到机器找到5个符合条件的点。

找色原理

查阅官方文档,我们注意到需要导包from airscript.screen import FindColors,以FindColors('426,346,#05D395|502,351,#05D015|676,569,#05D294')为例,上述含义:

在#05D395这个颜色的相对位置(x=502-426,y=351-346)有一个颜色值 #05D015,并且在#05D395这个颜色的相对位置(x=676-426,y=569-346) 存在一个颜色值 #05D294。 所有的颜色都属于第一个颜色点的定位点.

回归我们的需求,老师对单选框上采样了几个点,然后查找符合要求的点,结果查到了登录框,因为登录框也是橙色:

04实战 - 边学边用

查阅官方文档,发现找色支持选定查找的范围,FindColors(colors).rect(x,y,x1,y1)

04实战 - 边学边用 04实战 - 边学边用

在网页上,按住鼠标左键,圈出你要的范围,此刻投屏的右下角就显示你要的范围(1310,2393,1556,2520)。// 前面三个分别是设备分辨率、当前点色值、当前点坐标。

但是在我的设备上,这个单选框可能在(1310,2393,1556,2520)范围里,换个分辨率,这个单选框位置就变了呀。

我们尽量做活的脚本,其实控件是有控件范围这个属性的。

 

- THE END -

AffettoIris

11月26日23:35

最后修改:2023年11月26日
1

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论