PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛
0x1、引言
日常生活中,我每天都要从宝贵的 阳寿(时间) 里划出一小撮来完成各种 "日常",比如下面这些:
- APP → 签到、浏览、关注、点赞、活动参加,比如阿🐱阿🐶的农场、牧场、金币等;
- 游戏 → 单机游戏看视频广告30s,免费白嫖角色、装备等,联网游戏每日任务;
资本家 设计这些 "日常",有的是想保持用户日活,有的是想提高广告点击的收益。
一点蝇头小利,就想让我死心塌地给他们打零工,不能忍,翻身农奴把哥唱,这种浪费阳寿的日常 狗都不做!
汪汪汪,咳咳,我的家庭条件你又不是不知道,不是氪金大佬,也不是欧皇,非洲人只能靠肝了...
今年央视官宣某电商成为2020年春晚独家红包互动合作伙伴,邀请全面瓜分15亿红包和好物。
2021年中国人口14.13亿,人均分"一个亿",2333。
当然这 "一个亿" 可不是天上掉下来的,你得积极参加活动,多劳多得,比如炸年兽的活动每天必做:
任务列表是这样的:
为了让参与门槛尽量低一些,所以任务都设计得比较简单,就是费阳寿,可以大概分成这几类:
- 邀请好友助力 (一般不做,容易没朋友)
- 点击跳转其他页面(店铺、其他网页、自带小程序、微信小程序等)
- 点击跳转后浏览8s以上
- 点击跳转后浏览或加购4件商品
一开始傻乎乎地做了两天,后面就发觉不对劲了,至少得花上20分钟,虽说可以边摸鱼边点,但这种频繁切换注意力的感觉,让我很不适。
这是羊毛群里有人发自动炸年兽的快捷指令,巧了,刚从老婆那里继承旧的iPhone,立马安排上:
虽然不知道什么原理,但是自动做任务是真香啊,不过好景不长,没过几天就被和谐了:
无奈又回归 手动档,我恨啊!!!
手动了两天,实在受不了,开发仔怎能受这样的委屈,便琢磨着自己写一个自动做任务的脚本。
本身是Android仔,所以第一时间想到了Android的 无障碍服务(AccessibilityService) 自动点,但实际上不可行,因为它只适合Android原生页面元素的模拟操作,像这种webview加载H5的页面,他是无能为力的。(开发者模式 → 显示边界 就可以知道哪是原生,哪里不是原生):
接着我又想到使用adb命令直接点击坐标啥的,看似简单,写起来却非常繁琐,显示得封装,然后区域判定啥的,还得想办法实现。
前些天摸鱼逛掘金,一篇《网易UI自动化测试探索:Airtest+Poco》 映入眼帘,这不是我写爬虫总结文时提到的自动化测试工具吗?
当时大概了解了一下,因为没有应用场景,所以并没有去试试,这个工具的核心就是:两库一IDE
- Airtest库 → 图像识别,截图然后匹配对应位置就是在这里实现的,还有一些adb操作封装;
- Poco库 → 控件搜索,支持Android、iOS原生、大部分游戏引擎、微信小程序等;
- AirtestIDE → 专用编辑器,通过简易的操作即可快速产出自动化脚本。
用法啥的就不具体介绍了,直接看上述文章、官方文档、视频教程即可快速上手,有问题可以进答疑群问,娟姐还是非常有耐心的哈~
花了半天粗略看完,就忍不住动手尝试了~
Tips:风控原因,自动化操作可能会导致黑号,表现为秒杀秒不了,有些券领不到等,感兴趣想尝试的读者 风险自担 哈。至于笔者,黑不黑号无所谓,茅台啥的也没抢到过,也就平时薅薅羊毛,2333。
0x2、粗暴地面向过程——菜鸡脚本
见招拆招直接干,打开下载好的 Airtest IDE,接上安卓手机:
刷新ADB,看到设备后点下connect,右侧设备窗口出现手机界面,说明连接成功。
接着左侧 Poco辅助窗,下拉选中Android:
这些就是UI层级,然后想下大概的流程:
- 初始化:干掉APP → 打开APP → 找到游戏入口 → 点击入口
- 进入活动页:稍等片刻后 → 检查是否有弹窗,有关掉 → 检查爆竹是否已满,是领取
- 打开任务栏:判断任务栏是否打开,没有点击打开
- 完成任务:获取未完成任务,点击进入 → 进入后依次判断任务具体做啥 → 执行对应操作
啧啧,开始jio本的编写~
① 初始化
Airtest内部对常用的ADB操作进行了封装,通过简单的API调用即可与设备进行交互,具体可参见文档:《五、Airtest封装的ADB操作》,这里需要的是重启电商APP,不过好像没找到API,只找到了停止和启动:
参数传递的应用包名,所以得先拿到包名,IDE支持直接获取,点击设备窗:
点击 显示Android助手,打开电商App,接着Current App点击刷新:
拿到包名,然后就是定位到入口点击了,点击Poco辅助窗的小锁头:
接着点击设备窗口的入口元素:
Log查看窗就可以看到元素的信息:
然后就调下poco的API了,等待结点出现,然后点击,初始化部分的大概代码就是这样:
② 进入活动页
进入活动页后,有时会弹窗,需要关掉,然后炮竹满了的话收一下:
满的时候,这只憨憨年兽有一帧是这样的,点击Airtest辅助窗口的截屏按钮:
然后拖拉,抠出脸,代码会自动填充这个截图,是这样的:
有时会有弹窗,还得关下,同样是这样:
③ 打开任务栏
跟上面一样,都是抠图,然后点击,这里领任务位置是固定的,直接传入坐标点~
点击后会弹出任务栏:
④ 去完成
然后同样是抠图,点击去完成,进去后是各种子任务的依次执行了,先是8s的耗时任务:
接着是浏览加购4件商品和互动种草城:
好货特卖,城城分现金,还有跳转其他APP然后回来:
就这样简单粗暴地把自动化脚本写完了,虽然勉强能用(BUG巨多),但有两点必须优化下:
- 运行效率太低 → 点击去完成,打开页面后,还要执行各种判断,才知道具体执行什么操作,8s阳寿任务还好,那种点开就可以直接返回的,属实没必要等那么久。而且做什么任务,在点去完成的时候就知道了,没必要每次都判断;
- 代码改动繁琐 → 面向过程流水线,没有考虑扩展,改了页面或任务类型,代码改动起来太麻烦了。
0x3、优雅地面向对象——进阶脚本
重启APP,进活动页,打开任务栏这些步骤只执行一次,没太大必要做自动化,代码测试的时候也不好测,所以还是自己手动点击活动页,打开任务列表。
① 任务类型判定策略
先是第一个难点:任务类型的判定,比如 浏览并关注8s可得8000爆竹,人一看就知道该干嘛,进去没关注点下关注,等8s,然后把页面一关,就算完成任务了,但脚本不知道 啊。
一种解法是:人看完配置一个策略文件,脚本直接按照策略解析,比如:
{
"bt_1": { "task_type": "邀请" },
"bt_2": { "task_type": "点完就返回" },
"bt_3": { "task_type": "8s阳寿" },
"bt_4": { "task_type": "8s阳寿" },
"bt_5": { "task_type": "浏览4个商品" },
}
先不说每天都要折腾下配个策略,这些任务每完成一个,都会产生一个新任务,而且是随机的,谁顶得住啊?
所以想到另一种解法:OCR,生成截图,然后任务描述区域裁剪,接着文字识别,匹配关键字,执行对应任务。
考虑到OCR识别中文不一定准确,所以只判断任务描述中是否有关键字,比如8s、4个、关注等,也可以进行两串文本的匹配对判断,高于多少百分比认定为同一个任务。
差不多就可以开始敲码了,用到一些其他的第三方模块,AirtestIDE用起来可能不大顺手,所以还是用PyCharm吧,然后这两个库得pip装一下,顺带把百度OCR也装上:
pip install airtest
pip install pocoui
pip install baidu-aip
略去申请百度OCR服务的步骤,未实名认证一个月可白嫖200次,实名认证一个月可白嫖1000次,一天可能就用几十次,实名一次够了。当然,不够也没关系,可以多申请几家,弄一个白嫖OCR池,一个服务商份额用完就用另一个,也可以每次执行OCR操作时,随机用其中一家的OCR服务,跟代理IP池的玩法类似,代码也得写的灵活写,雏形示例如下:
② 任务定义
抽象出一个任务的父类:
然后就是各种任务的具体实现了:
- 阳寿任务 → 休眠15s,然后返回
- 浏览/加购任务 → 点击四个特定坐标点
- 关注任务 → 没关注点关注,然后返回
- 品牌墙 → 点击三个品牌,返回,滑动到顶部,重新点开任务栏
- 点完就返回 → 这里要注意互动种草城的处理
任务就这些,接着来写任务类型判定的逻辑~
③ 任务类型判定实现
流程就是,对应文字区域截图,然后根据Airtest定位到的去完成任务来判定具体执行哪个任务,先定义一些变量:
然后是初始化和截图:
再接着是去完成的核心代码,需要注意图片匹配总是命中去下单的问题:
然后就是匹配文字,然后调对应Task执行任务了~
而后调用处:
最后运行下看看效果:
啧啧啧,自动挡,就是爽~
0x4、小结
重写后的脚本清爽了不少,扩展起来也方便了一些,但还存在这些问题:
- 有些地方代码还不够优雅,比如截图部分,其实Airtest里就有这个API了,我还另外用PIL生成;
- 坐标写死,没有根据屏幕密度自适应,切换到其他手机上,会有问题,比如截图区域不对;
- 没必要频繁调用的OCR的API,描述文字部分其实来来去去就那些,可以保存图片识别结果,然后图片在执行OCR前,先于本地图片进行相似度的脚本,超过多少认定为同一图片,直接用之前的识别结果即可;
- 没做异常情况的处理,比如有时抽风弹对话框,得回退两次,有时自己回退等,得提供异常状态重置回复;
- 得再优化封装下,不止是这个脚本,还有其他APP的脚本,写尽可能少的代码就能轻松实现自动化;
大概就这些,想想每天到公司手机一插,就自动做各种浪费阳寿的日常,真香啊!!!
最后祝大家新春快乐~