自己写的蚂蚁森林脚本,自动收取自己和别人能量

喜欢的点个赞呗 2018.4.28更新 未经许可,谢绝转载

预计后续版本可能更新内容:

  1. 统计收集能量功能
  2. 增加更多分辨率支持
  3. 支持未root设备,利用无障碍辅助功能完成现有需要root权限完成的操作.
  4. 支持蹲守模式.如果是每天早上能量生成时间前,等待自己能量生成.(已完成,已发布)

这些需要时间,下班后才有点时间做,慢慢来吧.

重要 如果在排行榜出现异常 去把两处的getHasEnergyfriend(1) 全部替换为getHasEnergyfriend(2)

利用tasker早晨设备进行运动能量蹲守收集教程在 简书,注意你要根据早上运动能量生成时间来修改脚本中第二行的 var morningTime="07:10"; 并且至少在前后两分钟执行脚本,才能一直等待能量生成.

为了收集点能量简直操碎了心.自己写的蚂蚁森林脚本.配合tasker隔段时间解锁设备定时执行,在我手机上完美运行.我的设备是1920 1080 ,没其他设备测试,也懒得做匹配其他的,你可以自己改.或者等我闲的时候,我会加上其他兼容.也会更加优化脚本.

我的设备是6.0的,因为click及很多函数7.0以上才能用.根据搜索组件,利用UiObject组件的click点击我测试在我这也失效,改用了获取到组件位置后,调用Tap(x,y).点击、滑动的处理我用的是root的处理方式,没root自行应该改为无障碍的应该也可以话.分辨率方面我的是1080,1920.如果分辨率不一样,可能你还有做分辨率兼容性处理.

说一下达到的效果,把蚂蚁森林按钮要设置在常用应用中.先收取自己主页的能量,然后进入排行榜收集好友的能量.中途可以按下音量下键(可能失效,待解决)提前结束脚本运行.改改测测基本上现在运行还是挺完美的了,充分衡量了网络延迟和程序运行正常的平衡性.我是配合tasker设置的定时执行脚本,由Tasker唤醒设备,并解锁.打开支付宝,调用autojs插件执行任务.总之我觉得要想下载下来直接使用的话可能由于运行环境因素,你可能要调整一下.这个作为参考的价值还是稍微比较好的.

脚本地址

var myEnergeType=["线下支付","行走","共享单车","地铁购票","网络购票","网购火车票","生活缴费","ETC缴费","电子发票","绿色办公","咸鱼交易","预约挂号"];
var morningTime="07:10";
function tLog(msg) {
    toast(msg);
    console.log(msg)
}
/**
 * 获取权限和设置参数
 */
function prepareThings(){
    setScreenMetrics(1080, 1920);
    //请求截图
    if(!requestScreenCapture()){
        tLog("请求截图失败");
        exit();
    }
}
/**
 * 设置按键监听 当脚本执行时候按音量减 退出脚本
 */
function registEvent() {
    //启用按键监听
    events.observeKey();
    //监听音量上键按下
    events.onKeyDown("volume_down", function(event){
        tLog("脚本手动退出");
        exit();
    });
}
/**
 * 获取截图
 */
function getCaptureImg(){
    var img0 = captureScreen();
    if(img0==null || typeof(img0)=="undifined"){
        tLog("截图失败,退出脚本");
        exit();
    }else{
        return img0;
    }
}
/**
 * 默认程序出错提示操作
 */
function defaultException() {
    tLog("程序当前所处状态不合预期,脚本退出");
    exit();
}
/**
 * 等待加载收集能量页面,采用未找到指定组件阻塞的方式,等待页面加载完成
 */
function waitPage(type){
    // 等待进入自己的能量主页
    if(type==0){
        desc("消息").findOne();
    }
    // 等待进入他人的能量主页
    else if(type==1){
        desc("浇水").findOne();
    }
    //再次容错处理
    sleep(3000);
}
/**
 * 从支付宝主页进入蚂蚁森林我的主页
 */
function enterMyMainPage(){
    launchApp("支付宝");
    tLog("等待支付宝启动");
    var i=0;
    sleep(1000);
    //五次尝试蚂蚁森林入口
    while (!textEndsWith("蚂蚁森林").exists() && i<=5){
        sleep(2000);
        i++;
    }
    clickByText("蚂蚁森林",true,"请把蚂蚁森林入口添加到主页我的应用");
    //等待进入自己的主页
    waitPage(0);
}
/**
 * 进入排行榜
 */
function enterRank(){
    Swipe(520,1860,520,100);
    sleep(2500);
    clickByDesc("查看更多好友",0,true,"程序未找到排行榜入口,脚本退出");
    var i=0;
    //等待排行榜主页出现
    sleep(2000);
    while (!textEndsWith("好友排行榜").exists() && i<=5){
        sleep(2000);
        i++;
    }
    if(i>=5){
        defaultException();
    }
}
/**
 * 从排行榜获取可收集好有的点击位置
 * @returns {*}
 */
function  getHasEnergyfriend(type) {
    var img = getCaptureImg();
    var p=null;
    if(type==1){
        //411宽度 #a2cbb4  1032,1820  #30bf6c  1032,1787   -33     #52ca84  1032,1832   12     #ffffff  1032,1835   15
        p = images.findMultiColors(img, "#a2cbb4",[[0, -33, "#30bf6c"], [0,12, "#52ca84"],[0,15, "#ffffff"]], {
            region: [1032, 180, 1, 1700]
        });
    }else if(type==2){
        // 480宽度   基准点1775,832   #30bf6   -2,23 #ffffff   -5,16 #ffffff   0,-12  #30bf6c   0,44   #30bf6c
        p = images.findMultiColors(img, "#30bf6c",[[-2, 23, "#ffffff"], [-5,16, "#ffffff"],[0,-12, "#30bf6c"],[0,44, "#30bf6c"]], {
            region: [1069, 180, 7, 1680]
        });
    }
    if(p!=null){
        return p;
    }else {
        return null;
    }
}
/**
 * 判断是否好有排行榜已经结束
 * @returns {boolean}
 */
function isRankEnd() {
    if(descEndsWith("没有更多了").exists()){
        var b=descEndsWith("没有更多了").findOne();
        var bs=b.bounds();
        if(bs.centerY()<1920){
            return true;
        }
    }
    return false;
}
/**
 * 在排行榜页面,循环查找可收集好友
 * @returns {boolean}
 */
function enterOthers(){
    tLog("开始检查排行榜");
    var i=1;
    var ePoint=getHasEnergyfriend(1);
    //确保当前操作是在排行榜界面
    while(ePoint==null && textEndsWith("好友排行榜").exists()){
        //滑动排行榜 root方式的的点击调用.如无root权限,7.0及其以上可采用无障碍模式的相关函数
        Swipe(520,1800,520,300,1000);
        sleep(3000);
        ePoint=getHasEnergyfriend(1);
        i++;
        //检测是否排行榜结束了
        if(isRankEnd()){
            return false;
        }
        //如果连续32次都未检测到可收集好友,无论如何停止查找(由于程序控制了在排行榜界面,且判断了结束标记,基本已经不存在这种情况了)
        else if(i>32){
            tLog("程序可能出错,连续"+i+"次未检测到可收集好友");
            exit();
        }
    }
    if(ePoint!=null){
        //点击位置相对找图后的修正
        Tap(ePoint.x,ePoint.y+20);
        waitPage(1);
        clickByDesc("可收取",80);
        //进去收集完后,递归调用enterOthers
        back();
        sleep(2000);
        var j=0;
        //等待返回好有排行榜
        if(!textEndsWith("好友排行榜").exists() && j<=5){
            sleep(2000);
            j++;
        }
        if(j>=5){
            defaultException();
        }
        enterOthers();
    }else{
        defaultException();
    }
}
/**
 * 根据描述值 点击
 * @param energyType
 * @param noFindExit
 */
function clickByDesc(energyType,paddingY,noFindExit,exceptionMsg){
    if(descEndsWith(energyType).exists()){
        descEndsWith(energyType).find().forEach(function(pos){
            var posb=pos.bounds();
            Tap(posb.centerX(),posb.centerY()-paddingY);
            sleep(2000);
        });
    }else{
        if(noFindExit!=null && noFindExit){
            if(exceptionMsg !=null){
                tLog(exceptionMsg);
                exit();
            }else{
                defaultException();
            }
        }
    }
}
/**
 * 根据text值 点击
 * @param energyType
 * @param noFindExit
 */
function clickByText(energyType,noFindExit,exceptionMsg){
    if(textEndsWith(energyType).exists()){
        textEndsWith(energyType).find().forEach(function(pos){
            var posb=pos.bounds();
            Tap(posb.centerX(),posb.centerY()-60);
        });
    }else{
        if(noFindExit!=null && noFindExit){
            if(exceptionMsg !=null){
                tLog(exceptionMsg);
                exit();
            }else{
                defaultException();
            }
        }
    }
}
/**
 * 遍历能量类型,收集自己的能量
 */
function collectionMyEnergy(){
    var energyRegex=generateCollectionType();
    var checkInMorning=false;
    //如果是早上7点10分左右的话.等待主页能量出现 每隔一秒检测一次
    while(isMorningTime() && descEndsWith("行走").exists()){
        if (!checkInMorning){
            tLog("等待运动能量生成中...");
            checkInMorning=true;

        }
        descEndsWith("行走").find().forEach(function(pos){
            var posb=pos.bounds();
            Tap(posb.centerX(),posb.centerY()-80);
            sleep(1500);
        });
    }
    if(checkInMorning){
        tLog("运动能量收集完成");
    }
    if(descMatches(energyRegex).exists()){
        if(!checkInMorning){
            tLog("防止小树的提示遮挡,等待中");
            sleep(7000);
        }
        descMatches(energyRegex).find().forEach(function(pos){
            var posb=pos.bounds();
            Tap(posb.centerX(),posb.centerY()-80);
            sleep(2000);
        });
    }
}
/**
 * 结束后返回主页面
 */
function whenComplete() {
    tLog("结束");
    back();
    sleep(1500);
    back();
    exit();
}
/**
 * 根据能量类型数组生成我的能量类型正则查找字符串
 * @returns {string}
 */
function generateCollectionType() {
    var regex="/";
    myEnergeType.forEach(function (t,num) {
        if(num==0){
            regex+="(\\s*"+t+"$)";
        }else{
            regex+="|(\\s*"+t+"$)";
        }
    });
    regex+="/";
    return regex;
}
function isMorningTime() {
    var now =new Date();
    var hour=now.getHours();
    var minu=now.getMinutes();
    var targetTime=morningTime.split(":");
    if(Number(targetTime[0])==hour && Math.abs(Number(targetTime[1])-minu)<=2){
        return true;
    }else{
        return false;
    }
}
//程序主入口
function mainEntrence(){
    //前置操作
    prepareThings();
    //注册音量下按下退出脚本监听
    registEvent();
    //从主页进入蚂蚁森林主页
    enterMyMainPage();
    //收集自己的能量
    collectionMyEnergy();
    //进入排行榜
    enterRank();
    //在排行榜检测是否有好有的能量可以收集
    enterOthers();
    //结束后返回主页面
    whenComplete();
}
mainEntrence();
最后由 Kimipoker 编辑

好像在遇到下滑排行榜滑到需要加载时会出错

@wander 之前的有是有点问题,我以为我把这个帖子删除了更新了就没发过来,现在是最新的,你可以重新试一下虽然还是有很小几率会出现问题,我知道问题出在哪里,最近比较忙,暂时没时间来完善.

最后由 Kimipoker 编辑

膜拜大佬,非常棒,感谢分享哦。
大佬,能把tasker怎么解锁点亮屏幕的操作分享出来 一下吗

@oqyj 脚本我又更新了,你可以重新下载下,主要优化了流程和体验. tasker脚本那个等我过几天不忙的时候再分享出来吧.

谢谢大佬,我在运行时有两个问题,一是会反复进入能量剩余几分钟生成的好友(也可能是好友有能量,但是已经不能再抢了),二是无法检测到排行榜结束,i>32程序出错。另外,在程序最后退出之前,能不能添加一个往上滑的脚本,再检测是否有好友能量新生成?

@cezchrabbit自己写的蚂蚁森林脚本,自动收取自己和别人能量 中说:

  1. 请问它有能正常进入有能量的好有主页收集能量吗?你这个应该是分辨率导致的问题,因为查找好有那里是用的多点找色.分辨率不同,会出现找不准的情况.我的是1920*1080你的分辨率是多少?我想办法看看.你需要利用autojs的截图函数功能,在排行榜截图,截取包含可以收集的小手和还有倒计时的情况,同时包含最好,实在找不到一起的分开截图也行.放在zip压缩文件,发我邮件.jk969048824@163.com
  2. 排行榜不能正确结束的问题.排行榜检查结束机制是当前页面没有可以收集能量的好有,而且,屏幕最下端出现推荐你邀请的好友.所以不能结束的原因是有可能因为分辨率的原因,在最下端虽然出现了推荐能邀请的好有,但是一直错误的识别倒计时可收集的好有,进去又不能收集. 还有可能 你好有都加了,没出现推荐好有让你邀请?
  3. 至于往上滑的脚本,我觉得吧.因为正常运行的话最多一分多钟就收集完了,我再把等待时候和提示时间调短一点应该会更快,再往上没太大必要,如果是那样的话.要做到网络稳定性和速度的平衡还是得花点功夫,除非你是那种每天7.10分.想和他们比手速.那我程序应该设计成假定你是接近7.10分进入自己首页,当然我也可以根据当前时间来判断执行策略,然后一直等待,直到自己的能量能够收集,再去收集其他好有的.实际上是程序进入过后如果发现自己没能量,就马上进入排行榜收集去了.这些东西可以加,等以后版本慢慢更新吧.
最后由 Kimipoker 编辑

楼主好,本人Meizu Pro6s,分辨率1920x1080,Flyme6,安卓6.0,支付宝最新版。是有可以正常收取好友能量的。重新执行了几次脚本,发现在能量还剩16,36,33分钟的时候会点进去,但当时间剩余15分钟,就恢复正常了。猜测是某些数字下,多点找色会出现和小手一样的结果?
此外楼主说的截图,用哪个函数?直接系统截屏可以吗?本人是小白还没领会到…
再次感谢楼主!

@cezchrabbit
你执行这个脚本截图.截图保存在autojsImg1目录下.分辨率我们一样的.不知道是不是由于我改过dpi会有影像. 你多发几张不同情况的截图 我分析一下看看嘛.
//请求截图
function captureInLocal(){
if(!requestScreenCapture()){
toast("请求截图失败");
exit();
}
files.ensureDir("/sdcard/autojsImg1/");
var date =new Date();
var img = captureScreen("/sdcard/autojsImg1/"+date.getTime()+".png");
toast("Capture success");
}
captureInLocal();

坐等求楼主tasker自动解锁屏幕操作教程!

经过x次检测完之后就“结束脚本”了?没有收取好友的动作呢?谢谢

@leelei

你好 ,请问下你的设备分辨率是多少呢? 如果不是1920x1080 麻烦你参照下评论,给我发下你设备排行榜有数据时的相应截图,我没有其他分辨率设备,不好做适配.

@Kimipoker 你好,2560x1440 分辨率能帮忙适配一下吗?需要截图给你吗?

@chekky 你好,我想在csdn上我已经给你说过应该怎么做了.要改的地方就一句,因为这个确实和每个人的设备有关系.这个只是费时间的事情,如果你自己能够完成的话我不甚感激.因为我自己也有很多事情要做.

可以帮我写一个吗?打钱💰

  • 34
    帖子
  • 3501
    浏览

与 Auto.js 的连接断开,我们正在尝试重连,请耐心等待