跳到主要内容

· 阅读需 3 分钟
老陈

下面我们来演示一个简单的脚本, 方便新手入门, 最后的脚本源码请到下载中心的脚本案例中去下载

脚本要做的是在主页打开浏览器, 并搜索相应内容

首先, 我们点击控件载入, 分析出浏览器图标在什么地方, 在"系统应用"里

很好办, 我们发现有控件ID com.android.launcher3:id/preview_background

其它也是一样, 我们都能找到唯一的匹配参数, 如果一个参数不够, 那就多个

如果多个控件参数还是无法匹配, 我们可以匹配控件大小以及控件位置, 以及结合父子关系去匹配

然后我们输入搜索文本如何泡妞

我们要启用一下YY输入法, 如果我们要注入中文到编辑框里, 一般需要点击一下编辑框, 以进入输入状态

这里界面没有显示搜索按钮, 我们可以使用key_confim()注入搜索确认键到系统模拟器按下键盘的搜索键进行搜索

在编写代码的过程中, 如果我们只需要测试某行点击代码, 注释即可, 在pycharm中默认注释代码的快捷键是ctrl + / 如下所示, 我们只需要执行输入本文这句代码, 那我们注释其它代码即可.

最终的核心代码如下:

from yydsplus import *


def wait_activity(name: str):
sleep(1)
while True:
if device_foreground_activity() == name:
return


def main():
fg = device_foreground_activity()
# 我们开启引擎的日志调试, 开启这个会打印更多的日志
engine_set_debug(True)

# 确保返回到首页
key_home()
key_home()
# 打印当前活动界面名
util.print_with_time(">> 当前界面:" + fg)

# ui_match 返回一个控件数组, 所以我们直接选第一个进行点击
ui_match(resource_id="com.android.launcher3:id/preview_background")[0].click_node()
sleep(3)
ui_match(text="浏览器")[0].click_node()
wait_activity("com.android.browser.BrowserActivity")

sleep(3)
ui_match(resource_id="com.android.browser:id/url")[0].click_node()

# 为了提高我们脚本的稳定性, 我们一般要加点延时
sleep(4)

# 输入文本进行搜索
x_input_clear()
sleep(1)
x_input_text("如何泡妞")

# 确认搜索
key_confirm()

运行以上工程, 我们成功进入了界面

· 阅读需 3 分钟
老陈

🏊🏻‍♂️安装好环境之后, 我们便可以去尝试一下写代码

一定要实操实操

一般来说, 我们首先需要了解python的基本语法, 如果是小白也不用担心, 我们人类最好的学习方式就是模仿, 先照猫画虎对着已有的工程做, 然后再慢慢理解改动, 任何事物都是从感性认识再到理性认识的🌋.

接着我们了解引擎提供了什么封装好的自动化相关函数(即引擎函数), 安卓相关函数给我们用, 🤔思考怎样用自动化函数实现核心的点击功能

对于定位, 我们有图色与控件定位🔫, 如果可以使用控件定位🔫, 那是比图色要稳定很多, 不用考虑分辨率问题, 并且脚本的维护性也很高

我们所说的图色包括了ocr, ocr对于艺术文字的识别率不高, 对于大部分游戏来说, 都是艺术字体, ocr识别几乎无效

如果我们的脚本包括千变万化的人物角色或者一些复杂的半透明图片, 那图像识别和ocr识别也是无效的, 我们需要使用深度学习技术的yolo来识别定位到我们的目标

当然, 如果用控件定位, 虽然我们没有使用无障碍功能, 但是仍然可能被一些app风控到, 因为获取控件的时候系统会回调到app

🤠对于脚本开发, 我们往往是一个功能,一个操作一个操作地来写, 然后像搭积木一样搭起来的

🤓对于一些系统类的任务性操作, 我们可以使用shell

😋如果我们需要用到更复杂的功能, 我们就用三方库, 比如联网请求功能

🤤如果我们需要调用安卓代码, 比如我们要实现安卓的通讯录写入, 我们可以使用python调用java功能

😇久而久之, 我们代码写多了, 就会慢慢形成很多模版, 可以快速写出很复杂的脚本, 只需要填图填控件即可

· 阅读需 1 分钟
老陈

假如我的脚本开发机的屏幕分辨率是1080x2400, 我们可以等比缩放坐标, 以提高脚本的兼容性。

def scal_pos_1080_2400(x, y) -> (int, int):
"""
对于纵向(portrait)屏幕坐标的缩放
"""
return int(screen._dw * x / 1080), int(screen._dh * y / 2400)

def scal_pos_2400_1080(x, y) -> (int, int):
"""
对于横向(landscape)屏幕坐标的缩放
"""
return int(screen._dh * x / 2400), int(screen._dh * y / 1080)


click(100, 100) # 全分辨率兼容不好
click(*scal_pos_1080_2400(100, 100)) # 全分辨率兼容好

· 阅读需 1 分钟
老陈

必要资源


硬件配备

32G + 内存, 2060+ 英伟达显卡

操作步骤

1.准备好数据集, 使用labelme进行标注, 并转换为coco数据集

2.把yolov5 源码下载到本地电脑磁盘

3.查看训练yaml配置, 自己模仿写一个

4.查看数据集配置, 自己模仿写一个

5.开始训练

6.转换导出pt模型到onnx

7.onnx转换为ncnn

8.进行ncnn optimize优化

9.编辑ncnn(optimize)模型中的param文件, 如下图

使用Yyds.Auto加载模型

# 加载模型
model_yolo_reload("example.bin", "example.param")
# 以当前屏幕为目标, 进行前向推导计算
screen_yolo_locate()

· 阅读需 2 分钟
老陈

脚本代码

import hashlib

def yolo_find_x(specify_labels=None, min_prob: float = 0.9, use_gpu=False) -> List[ResYolo]:
"""
通过yolo算法识别当前屏幕内容

:param specify_labels: 是否寻找指定label内容
:param min_prob: 最低置信率
:param use_gpu: 是否使用gpu运算

:returns: 识别结果列表
"""
if specify_labels is None:
specify_labels = []
str_fds = screen_yolo_locate(use_gpu=use_gpu)
sp_fds = str_fds.split('\n')
results: List[ResYolo] = list()
for fd in sp_fds:
if fd != "":
result = re.match(
r'{label=\'(.*)\', cx=(\d+), cy=(\d+), x=(\d+.\d+), y=(\d+.\d+), w=(\d+.\d+), h=(\d+.\d+), '
r'prob=(\d+.\d+)}',
fd).groups()
res_yolo = ResYolo(
result[0],
int(result[1]),
int(result[2]),
float(result[3]),
float(result[4]),
float(result[5]),
float(result[6]),
float(result[7]),
)
if res_yolo.prob >= min_prob:
if len(specify_labels) > 0:
for it in specify_labels:
if re.match(it, res_yolo.label):
results.append(res_yolo)
else:
results.append(res_yolo)
return results

# 对文件进行md5计算, 检查文件是否完整
def md5_file(path):
md5 = hashlib.md5()
f = open(path, mode="rb")
md5.update(f.read())
f.close()
md5_sum = md5.hexdigest()
return md5_sum


def main():
m1 = os.path.exists("/data/local/tmp/yyds.bin") and md5_file("/data/local/tmp/yyds.bin")
m2 = os.path.exists("/data/local/tmp/yyds.bin") and md5_file("/data/local/tmp/yyds.param")
if m1 != "dd90463d425e889abb0015bca59f2537" or m2 != "e89facf887d5088177d262119a8fb89b":
toast("未正确下载ncnn模型文件, 正在下载")
download("https://----------.com/auto/last-sim-opt.bin", "/data/local/tmp/yyds.bin")
download("https://----------.com/auto/last-sim-opt.param", "/data/local/tmp/yyds.param")
else:
toast("模型已正确配置")

while True:
time.sleep(5)
print("扫描识别中")
yolo_res_list = yolo_find_x()
if len(yolo_res_list) > 0:
for yolo_res in yolo_res_list:
if yolo_res.label == "label2" or yolo_res.label == "label1":
print("点击:", yolo_res)
time.sleep(1)
click(yolo_res.cx, yolo_res.cy)
toast(str(yolo_res))