最近一直在研究冰狐智能辅助,上次利用冰狐智能辅助实现了一个免费的个人收款系统,用起来还行,说实话刚开始我有怀疑过平台的稳定性,现在看来是有点多虑了。最近看官网更新了一个针对菜鸟设计的通过配置直接生成脚本功能「自动构建」,个人觉得很好奇,有点高大上,于是利用约会的时间研究了一把。用「自动构建」,没写一行代码,实现了一个薅羊毛程序(纯属个人兴趣研究,禁止用于任何商业用途),现把该薅羊毛程序作为例子进行讲解,分享菜鸟(不会编程的同学)是如何快速实现辅助功能的。
准备工作
- 手机端安装「冰狐智能辅助」,详细安装过程请看这里。
- 手机端安装「爱奇艺极速版」v1.10.6,注意,必须安装这个版本,不同的版本操作界面可能不同,可能会导致辅助功能失效。点击这里从豌豆荚官网下载该版本。
- 注册「爱奇艺极速版」用户并登陆。
制作辅助功能
- 进入「移动端」/「自动构建」,新建名为”爱奇艺极速版“的自动构建。
- 点击“配置源码”按钮,将如下json数据粘贴进去,保存。
-
{
-
"type": "root",
-
"children": [{
-
"type": "declareVar",
-
"var": [{
-
"name": "ret",
-
"type": "normal",
-
"initType": "null",
-
"initValue": "null"
-
}, {
-
"name": "view",
-
"type": "normal",
-
"initType": "null",
-
"initValue": "null"
-
}, {
-
"name": "viewContainer",
-
"type": "normal",
-
"initType": "null",
-
"initValue": "null"
-
}, {
-
"name": "item",
-
"type": "normal",
-
"initType": "null",
-
"initValue": "null"
-
}],
-
"desc": "变量声明"
-
}, {
-
"type": "launchApp",
-
"packageName": "com.qiyi.video.lite",
-
"findTag": "txt:首页-",
-
"failed": "exitPopup",
-
"maxStep": "30",
-
"children": [{
-
"type": "log",
-
"log": "启动app成功",
-
"desc": "启动成功日志",
-
"info": [ "string-app启动成功"],
-
"log_type": "log"
-
}, {
-
"type": "switchPage",
-
"returnVar": "",
-
"findTag": "txt:开宝箱-",
-
"checkTag": "txt:活动规则-",
-
"root": "",
-
"click": "true",
-
"failed": "exitPopupWithAD",
-
"descendant": "[]",
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"children": [{
-
"type": "log",
-
"desc": "开始日志",
-
"log_type": "log",
-
"info": [ "string-进入任务"]
-
}, {
-
"type": "task",
-
"scrollCount": "2",
-
"returnTag": "txt:活动规则-",
-
"taskDeal": [{
-
"key": "txt^:免费抽大奖-",
-
"value": {
-
"type": "switchPage",
-
"desc": "切换到幸运大转盘",
-
"returnVar": "",
-
"findTag": "txt^:免费抽大奖-",
-
"checkTag": "txt:幸运大转盘-",
-
"root": "",
-
"click": "true",
-
"failed": "exitPopupWithAD",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"children": [{
-
"type": "loop",
-
"desc": "循环多次处理抽奖",
-
"class": "2",
-
"startIndex": "0",
-
"endIndex": "20",
-
"children": [{
-
"type": "findView",
-
"desc": "搜索控件",
-
"viewDeal": [{
-
"key": "txt^:恭喜到账-traverse_one_by_one",
-
"value": {
-
"type": "loop",
-
"desc": "退出到账",
-
"class": "4",
-
"container": "view",
-
"descendant": "[-1,-1]",
-
"children": [{
-
"type": "if",
-
"desc": "条件处理",
-
"expr": "item.clickable",
-
"children": [{
-
"type": "log",
-
"desc": "日志",
-
"log_type": "log",
-
"info": [ "string-click x,and exit"]
-
}, {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "item"
-
}, {
-
"type": "break",
-
"desc": "跳出循环"
-
}]
-
}]
-
}
-
}, {
-
"key": "txt$:后再来-",
-
"value": {
-
"type": "break",
-
"desc": "跳出循环"
-
}
-
}, {
-
"key": "txt^:lottery-list-",
-
"value": {
-
"type": "custom",
-
"desc": "抽奖",
-
"code": "var txt = view.parent.parent.parent[2][0].text;\nconsole.log('txt:' + txt);\nvar num = parseInt(txt);\nif (num > 0) {\ngestureClick((view.left + view.right) / 2, (view.top + view.bottom) / 2, {afterWait: 8000});\nconsole.log('点击开始抽奖');\n} else {\nconsole.log('抽奖结束');\nbreak;\n}"
-
}
-
}, {
-
"key": "txt^:lottery-list-",
-
"value": {
-
"type": "if",
-
"desc": "条件处理",
-
"expr": "parseInt(view.parent.parent.parent[2][0].text)>0",
-
"children": [{
-
"type": "click",
-
"desc": "点击控件",
-
"class": "4",
-
"duration": "500",
-
"beforeWait": "0",
-
"afterWait": "8000",
-
"x": "0",
-
"y": "0",
-
"unit": "px"
-
}]
-
}
-
}],
-
"root": "",
-
"failed": "exitPopupWithAD",
-
"duration": "500",
-
"maxStep": "10",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"false": {
-
"type": "break",
-
"desc": "跳出循环"
-
}
-
}],
-
"descendant": []
-
}, {
-
"type": "back2Page",
-
"desc": "返回页面",
-
"returnVar": "",
-
"tag": "txt:我的|txt:活动规则-",
-
"root": "",
-
"backFirst": "true",
-
"failed": "",
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}],
-
"false": {
-
"type": "log",
-
"desc": "日志",
-
"log_type": "error",
-
"info": [ "string-切换到大转盘失败"]
-
}
-
}
-
}, {
-
"key": "txt:开宝箱领金币|txt$:每日可领-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [],
-
"beforeWait": "0",
-
"afterWait": "1000",
-
"target": "view"
-
}
-
}],
-
"maxDealCount": "8",
-
"failed": "exitPopupWithAD",
-
"desc": "任务处理",
-
"removeTag": true
-
}, {
-
"type": "log",
-
"desc": "结束日志",
-
"log_type": "log",
-
"info": [ "string-任务结束"]
-
}],
-
"desc": "切换到任务频道",
-
"false": {
-
"type": "log",
-
"desc": "日志",
-
"log_type": "error",
-
"info": [ "string-进入任务失败"]
-
}
-
}, {
-
"type": "switchPage",
-
"returnVar": "",
-
"findTag": "txt:首页-",
-
"checkTag": "txt:电视剧-",
-
"root": "",
-
"click": "true",
-
"failed": "exitPopupWithAD",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"children": [{
-
"type": "mainLoop",
-
"minRunTime": "2",
-
"maxRunTime": "5",
-
"minScrollCount": "1",
-
"maxScrollCount": "3",
-
"containerTag": "cn:androidx.recyclerview.widget.RecyclerView-",
-
"failed": "exitPopupWithAD",
-
"children": [{
-
"type": "log",
-
"log": "开始看视频了哦",
-
"desc": "日志",
-
"info": [ "string-开始看电视了哦"],
-
"log_type": "log"
-
}, {
-
"type": "loopPicker",
-
"desc": "从循环中挑选某些项处理",
-
"startIndex": "1",
-
"lastIndex": "1",
-
"random": true,
-
"children": [{
-
"type": "click",
-
"desc": "点击电视",
-
"class": "2",
-
"click": "true",
-
"descendant": [],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "sChild"
-
}, {
-
"type": "findView",
-
"desc": "查看是否进入电视",
-
"returnVar": "",
-
"tag": "txt*:/|txt:金蛋奖励-",
-
"root": "",
-
"failed": "exitPopup",
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"children": [{
-
"type": "loop",
-
"desc": "看电视",
-
"breakTag": "txt:完成-",
-
"failed": "",
-
"minRunTime": "0.5",
-
"maxRunTime": "1.2",
-
"class": 1
-
}],
-
"viewDeal": [{
-
"key": "txt*:/|txt:金蛋奖励-",
-
"value": {
-
"type": "loop",
-
"desc": "看电视",
-
"class": 1,
-
"breakTag": "txt:完成-",
-
"failed": "exitPopup",
-
"minRunTime": "0.7",
-
"maxRunTime": "1.2",
-
"descendant": [],
-
"children": [{
-
"type": "click",
-
"desc": "关闭广告",
-
"class": 1,
-
"tag": "txt:关闭此广告-",
-
"root": "",
-
"click": "true",
-
"failed": "",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}]
-
}
-
}],
-
"false": {
-
"type": "log",
-
"desc": "日志",
-
"log_type": "log",
-
"info": [ "string-进入电视失败"]
-
}
-
}, {
-
"type": "click",
-
"desc": "领金币",
-
"class": 1,
-
"tag": "txt:领金币-",
-
"root": "",
-
"click": "true",
-
"failed": "",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}, {
-
"type": "click",
-
"desc": "领不固定金币",
-
"class": 1,
-
"tag": "txt^:领-",
-
"root": "",
-
"click": "true",
-
"failed": "",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}, {
-
"type": "back2Page",
-
"desc": "返回页面",
-
"returnVar": "",
-
"tag": "txt:我的-",
-
"root": "",
-
"backFirst": "true",
-
"failed": "",
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}]
-
}],
-
"returnTag": "txt:我的-",
-
"skipProb": "80",
-
"desc": "滚动屏幕看电视",
-
"findContainerFailed": {}
-
}],
-
"desc": "切换到电视剧频道",
-
"false": {
-
"type": "log",
-
"desc": "日志",
-
"log_type": "error",
-
"info": [ "string-进入看电视失败"]
-
}
-
}, {
-
"type": "switchPage",
-
"desc": "切换到短视频",
-
"returnVar": "",
-
"findTag": "txt:短视频-",
-
"checkTag": "txt:推荐-",
-
"root": "",
-
"click": "true",
-
"failed": "exitPopupWithAD",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"false": {
-
"type": "log",
-
"desc": "切换失败日志",
-
"log_type": "error",
-
"info": [ "string-切换短视频失败"]
-
},
-
"children": [{
-
"type": "mainLoop",
-
"desc": "主循环",
-
"containerTag": "cn:androidx.recyclerview.widget.RecyclerView-",
-
"returnTag": "-",
-
"skipProb": "0",
-
"failed": "exitPopup",
-
"minRunTime": "2",
-
"maxRunTime": "3",
-
"minScrollCount": "1",
-
"maxScrollCount": "1",
-
"children": [{
-
"type": "log",
-
"desc": "日志",
-
"log_type": "log",
-
"info": [ "string-开始看小视频了"]
-
}, {
-
"type": "loop",
-
"desc": "循环",
-
"breakTag": "",
-
"failed": "",
-
"minRunTime": "0.1",
-
"maxRunTime": "0.5",
-
"class": 1
-
}, {
-
"type": "break",
-
"desc": "跳出循环"
-
}]
-
}]
-
}],
-
"false": {
-
"type": "log",
-
"log": "启动APP失败",
-
"desc": "日志",
-
"log_type": "error",
-
"info": [ "string-启动app失败"]
-
},
-
"desc": "启动APP"
-
}, {
-
"type": "popup",
-
"name": "exitPopup",
-
"exitPopupDeal": [{
-
"key": "txt:暂不升级|txt:我知道了-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "txt:猜你想看-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": 1,
-
"tag": "txt:取消-",
-
"root": "",
-
"click": "true",
-
"failed": "",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}
-
}, {
-
"key": "txt^:再赚-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "false",
-
"descendant": [],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "txt:恭喜获得-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [- 1, 4],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "txt^:恭喜到账-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [- 1, 2, 0],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "txt:继续赚钱-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": "[-1,-1,-1,1]",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "txt^:打开日历提醒-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": "[-1,7]",
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}],
-
"false": "[]",
-
"desc": "处理弹窗"
-
}, {
-
"type": "popup",
-
"name": "exitPopupWithAD",
-
"exitPopupDeal": [],
-
"false": [ "exitPopup", "dealAD"],
-
"desc": "处理弹窗和广告"
-
}, {
-
"type": "ad",
-
"enterWindowList": "[\"com.mcto.sspsdk.ssp.activity.QyTrueViewActivity\"]",
-
"enterTags": "txt*:s后可领取奖励-",
-
"breakTags": "txt:开宝箱|txt:我的|txt^:再赚|txt:继续赚钱|txt:幸运大转盘-",
-
"exitDeal": [{
-
"key": "txt:关闭-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "txt:恭喜获得-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": "2",
-
"click": "true",
-
"descendant": [- 1, 4],
-
"beforeWait": "0",
-
"afterWait": "0",
-
"target": "view"
-
}
-
}, {
-
"key": "cn:android.widget.ImageView-find_all|clickable",
-
"value": {
-
"type": "loop",
-
"desc": "循环",
-
"class": "4",
-
"container": "viewContainer",
-
"children": [{
-
"type": "custom",
-
"desc": "自定义模块,直接写入代码",
-
"code": "if (item.width == item.height && item.width < 80 && item.width > 40 && item.top < 100 && item.right > (rsScreenWidth - 20)) {\nclick(item, {click: true});\nconsole.log('click x');\nbreak;\n}"
-
}],
-
"descendant": "[]"
-
}
-
}, {
-
"key": "txt:继续观看视频可获得奖励-",
-
"value": {
-
"type": "click",
-
"desc": "点击控件",
-
"class": 1,
-
"tag": "txt:继续观看-",
-
"root": "",
-
"click": "true",
-
"failed": "",
-
"descendant": [],
-
"duration": "500",
-
"maxStep": "5",
-
"beforeWait": "0",
-
"afterWait": "0"
-
}
-
}],
-
"desc": "处理广告"
-
}, {
-
"type": "windowChange",
-
"windowDeal": [],
-
"desc": "窗口变化处理"
-
}, {
-
"type": "notification",
-
"children": [],
-
"filter": "",
-
"desc": "通知处理"
-
}],
-
"desc": "根模块"
-
}
-
- 点击“编译”按钮,把构建编译成js代码。
- 进入「移动端」/「移动端脚本」,系统会自动创建一个“爱奇艺极速版”js脚本,点击“发布”按钮,发布脚本。
- 点击“运行”按钮,选择设备,执行脚本,一个自动薅羊毛的辅助程序就完成啦😊。
原理分析
看到这,其实最核心的就是如何得到配置json数据。下面我们一起来看下我是如何配置的:
进入「移动端」/「自动构建」,选择“爱奇艺极速版”,然后点击“配置构建”按钮。这时候弹出一个配置界面,如下图所示:
配置由模块组成,每个模块由模块属性和子模块组成。一般的模块会直接执行子模块,有的带条件的模块,当条件为true或者执行结果为true时才执行子模块,注意:子模块是按按顺序执行。整个配置其实就是一个树形结构,上图就是根模块。下面来介绍下每个模块作用:
变量声明
声明一些后面模块要用的通用变量,系统会自动生成几个常用的变量,个人感觉绝大部份情况下系统默认生成的就够用了😄。点击“编辑”按钮,再点击“查看/编辑变量声明”,显示如下变量:
启动APP
如果打算启动和处理APP,必须添加这个模块。点击该模块的“编辑”按钮,属性和子模块如下图所示:
「每个属性行的最后都有一个说明,鼠标移动上去会自动显示详细说明。」
属性如下:
- packageName,APP的包名
- findTag,这个是用来检测app是否已经启动。app启动了,首页中如果出现该tag,则表示启动成功。
- false,启动app失败后会执行该模块,打了个log😯。
- failed,用来处理随机弹窗的问题,如果系统随机弹出什么升级啊等窗口时,这个可以自动处理🐂。
- maxStep,检测是否启动,最多find几次tag,默认好像是30次。
成功启动app后,会自动按顺序执行子模块:
- 打log,用于调试吧。
- 切换到任务频道,做任务。
- 切换到电视剧频道,看电视剧。
- 切换到短视频频道,看短视频。
处理弹窗
用于处理app随机弹出的各种窗口,比如:升级、青少年模式、处理成功等等对话框。
属性如下:
- exitPopupDeal,用于处理弹窗。点击后面的"查看/编辑map"
- false,模块数组。当无法处理弹窗时,会按顺序执行模块,如果返回true则不执行,否则继续执行下一个。
处理弹窗和广告
用于即有可能出现弹窗也有可能出现广告的场景。false属性值["exitPopup","dealAD"],表示先处理弹窗,如果失败,则看看是否是广告,处理广告。
处理广告
处理弹出广告的情况,当广告完成后自动退出广告。广告不会自动触发,一般是在点击某个按钮后弹出广告。
属性如下:
- enterWindows,广告窗口className的数组,当出现其中一个窗口时,表示进入广告。
- enterTags,广告窗口中某个标识性控件的tag数组,当出现其中一个tag时,表示进入了广告。
- breakTags,广告退出后显示页面的标志性tag数组,当出现其中一个tag时,表示广告已经退出。
- exitDeal,退出处理,当出现点击退出广告的按钮时,点击按钮。
窗口变化处理
可以用于处理比如。当窗口改变后,系统会自动触发该模块。
通知处理
用于处理各种通知,比如微信消息,短信等等。当出现通知时,系统会自动触发该模块。
总结
通过这几天的研究,总体感觉还可以,能通过配置完成绝大多数功能。但也有缺点,就是文档太少了,很多属性需要自己研究,希望官方以后会多多完善文档。
本文只介绍了部分模块,还有其他模块这里没有介绍完,如果大家感兴趣的话,我后续再继续出专题,有任何问题,欢迎大家留言,一起交流😊