京东618拆快递活动Autojs脚本 安卓机可用
活动已经开始几天啦,有朋友问脚本,这里分享个autojs的脚本,安卓机可用哈这么多天了才想到要发下
autojs脚本程序,用于完成安卓设备上的重复性操作.(可以完成拆快递活动中的大部分任务)
1、Autojs版本为4.1.x(免费版)
2、开启脚本也会打开活动,任务未完成可以多运行2遍
3、有可能出现空指针,undefined等异常(很有可能是网络问题,把时间参数调大点,重新启动脚本即可).
4、京东推荐切换tbs内核运行。
方法如下:
给京东客服发送 debugtbs.qq.com,然后点击打开
选择安装线上内核,安装完成之后自动重启,选择DebugX5,不显示请先安装内核则为成功。否则请强行停止京东APP,重复步骤。
运行任务尝试
1、下载地址:Autojs 下载
2、手机下载apk安装,完成后开启无障碍模式
3、将脚本保存为js文件导入手机,在autojs app内导入(打开界面那个+号)
4、其他使用方法可以参考autojs的官方文档,不一一说了
5、使用该脚本有可能出现活动火爆(也就是无法参与活动),请谨慎使用
下载地址:https://meituan.lanzoub.com/iUwp40xc78ne
const VERSION = '2023618-G' if (!auto.service) { toast('无障碍服务未启动!退出!') exit() } let showVersion = function () { console.log('当前版本:' + VERSION) console.log('一起活动吧:https://www.yqhd8.com') toast('当前版本:' + VERSION) } console.show() showVersion() function getSetting() { let indices = [] autoOpen && indices.push(0) autoMute && indices.push(1) autoJoin && indices.push(2) indices.push(3) let settings = dialogs.multiChoice('任务设置', ['自动打开京东进入活动。多开或任务列表无法自动打开时取消勾选', '自动调整媒体音量为0。以免直播任务发出声音,首次选择需要修改系统设置权限', '自动完成入会任务。京东将授权手机号给商家,日后可能会收到推广短信', '此选项用于保证选择的处理,勿动!'], indices) if (settings.length == 0) { toast('取消选择,任务停止') exit() } if (settings.indexOf(0) != -1) { storage.put('autoOpen', true) autoOpen = true } else { storage.put('autoOpen', false) autoOpen = false } if (settings.indexOf(1) != -1) { storage.put('autoMute', true) autoMute = true } else { storage.put('autoMute', false) autoMute = false } if (settings.indexOf(2) != -1) { storage.put('autoJoin', true) autoJoin = true } else { storage.put('autoJoin', false) autoJoin = false } } let storage = storages.create("jd_task"); let autoOpen = storage.get('autoOpen', true) let autoMute = storage.get('autoMute', true) let autoJoin = storage.get('autoJoin', true) getSetting() if (autoMute) { try { device.setMusicVolume(0) toast('成功设置媒体音量为0') } catch (err) { alert('首先需要开启修复音量权限,请开启后再次运行脚本') exit() } } console.log('开始完成京东任务...') console.log('按音量下键停止') device.keepScreenDim(30 * 60 * 1000) // 防止息屏30分钟 // 自定义取消亮屏的退出方法 function quit() { device.cancelKeepingAwake() exit() } // 监听音量下键 function registerKey() { try { events.observeKey() } catch (err) { console.log('监听音量键停止失败,应该是无障碍权限出错,请关闭软件后台任务重新运行。') console.log('如果还是不行可以重启手机尝试。') quit() } events.onKeyDown('volume_down', function (event) { console.log('京东任务脚本停止了') console.log('请手动切换回主页面') startCoin && console.log('本次任务开始时有' + startCoin + '快递箱') quit() }) } threads.start(registerKey) // 自定义一个findTextDescMatchesTimeout function findTextDescMatchesTimeout(reg, timeout) { let c = 0 while (c < timeout / 50) { let result = textMatches(reg).findOnce() || descMatches(reg).findOnce() if (result) return result sleep(50) c++ } return null } // 打开京东进入活动 function openAndInto() { console.log('正在打开京东App...') if (!launch('com.jingdong.app.mall')) { console.log('可能未安装京东App') } else { console.log('等待京东打开') for (let i = 0; i < 20; i++) { if (currentPackage() == 'com.jingdong.app.mall') break sleep(400) } if (currentPackage() != 'com.jingdong.app.mall') { console.log('程序检测京东app打开失败,请注意') } } sleep(2000) console.log('进入活动页面') app.startActivity({ action: "VIEW", data: 'openApp.jdMobile://virtual?params={"category":"jump","action":"to","des":"m","sourceValue":"JSHOP_SOURCE_VALUE","sourceType":"JSHOP_SOURCE_TYPE","url":"https://u.jd.com/Ou1Dq89","M_sourceFrom":"mxz","msf_type":"auto"}' }) } // 获取快递箱数量 function getCoin() { let anchor = text('累计已拆').findOne(5000) if (!anchor) { console.log('找不到累计控件') return false } let coin = anchor.parent().child(1).text() if (coin) { return parseInt(coin) } else { return false } } // 打开任务列表 function openTaskList() { console.log('打开任务列表') let taskListButton = text('拆快递').findOne(20000) if (!taskListButton) { console.log('无法找到任务列表控件,请参照软件内的说明更换web内核。') quit() } taskListButton.click() console.log('等待任务列表') if (!findTextDescMatchesTimeout(/.*每做一次任务.*/, 5000)) { console.log('似乎没能打开任务列表,重试') taskListButton.click() } if (!findTextDescMatchesTimeout(/.*每做一次任务.*/, 10000)) { console.log('似乎没能打开任务列表,退出!') console.log('如果已经打开而未检测到,请参照软件内的说明更换web内核。') quit() } } // 关闭任务列表 function closeTaskList() { console.log('关闭任务列表') let anchor = findTextDescMatchesTimeout(/.*每做一次任务.*/, 5000) if (!anchor) { console.log('无法找到任务奖励标识') return false } anchor = anchor.parent() let closeBtn = anchor.child(anchor.childCount() - 2) // tbs if (!closeBtn.clickable()) { closeBtn = anchor.child(anchor.childCount() - 1) // webview } return closeBtn.click() } // 重新打开任务列表 function reopenTaskList() { sleep(3000) closeTaskList() sleep(3000) openTaskList() sleep(5000) } // 获取未完成任务,根据数字标识,返回任务按钮、任务介绍、任务数量(数组) function getTaskByText() { let tButton = null, tText = null, tCount = 0, tTitle = null console.log('寻找未完成任务...') let anchor = textMatches(/^(去完成|去打卡)$/).findOnce() if (anchor) { // 如果找不到任务,直接返回 let tasks = anchor.parent().parent().parent().children() tasks.pop() for (let i = 0; i < tasks.length - 2; i += 5) { let task = tasks.slice(i, i + 5) try { tTitle = task[1].text() let r = task[2].text().match(/(\d*)\/(\d*)/) if (!r) continue tCount = (r[2] - r[1]) console.log(tTitle, tCount) button = task[4] if (!button.child(0).child(0).text().match(/去完成|去领取|去打卡/)) continue // log(tasks) if (tCount) { // 如果数字相减不为0,证明没完成 tText = task[3].text() if (!autoJoin && tText.match(/成功入会/)) continue if (tTitle.match(/下单|小程序|裂变|白条|小游戏/) || tText.match(/绑卡/)) continue tButton = button break } } catch (err) { console.log(err) } } } else { console.log('任务提示未找到') } return [tButton, tText, tCount, tTitle] } // 返回任务列表并检查是否成功,不成功重试一次,带有延时 function backToList() { sleep(500) back() for (let i = 0; i < 5; i++) { // 尝试返回3次 if (!findTextDescMatchesTimeout(/.*每做一次任务.*/, 5000)) { console.log('返回失败,重试返回') sleep(2000) back() continue } else { break } } sleep(3000) } // 浏览n秒的任务 function timeTask() { console.log('等待浏览任务完成...') let c = 0 while (c < 40) { // 0.5 * 40 = 20 秒,防止死循环 if ((textMatches(/获得.*?快递箱/).exists() || descMatches(/获得.*?快递箱/).exists())) // 等待已完成出现 break if ((textMatches(/已.*?浏.*?览/).exists() || descMatches(/已.*?浏.*?览/).exists())) { // 失败 console.log('上限,返回刷新任务列表') return false } if ((textMatches(/出.*?错.*?了/).exists() || descMatches(/出.*?错.*?了/).exists())) { console.log('任务出错,返回刷新任务列表') return false } if (textMatches(/.*滑动浏览.*[^可]得.*/).exists()) { console.log('进行模拟滑动') swipe_flag = 1 swipe(device.width / 2, device.height - 200, device.width / 2 + 20, device.height - 500, 500) c++ } // 弹窗处理 let pop = text('升级开卡会员领好礼') if (pop.exists()) { pop.findOnce().parent().parent().child(2).click() console.log('关闭会员弹窗') } sleep(500) c++ } if (c > 39) { console.log('未检测到任务完成标识。') return false } console.log('已完成,准备返回') return true } // 入会任务 function joinTask() { let check = textMatches(/.*确认授权即同意.*|.*我的特权.*|.*立即开卡.*|.*解锁全部会员福利.*/).findOne(8000) if (!check) { console.log('无法找到入会按钮,判定为已经入会') return true } else if (check.text().match(/我的特权/)) { console.log('已经入会,返回') return true } else { sleep(2000) if (check.text().match(/.*立即开卡.*|.*解锁全部会员福利.*|授权解锁/)) { if (check.text() == '授权信息,解锁全部会员福利') { check = text('去升级').findOnce() if (!check) { console.log('此类型无法找到升级按钮,入会失败') return false } } let btn = check.bounds() console.log('即将点击开卡/解锁福利/升级,自动隐藏控制台') sleep(500) console.hide() sleep(500) click(btn.centerX(), btn.centerY()) sleep(500) console.show() sleep(5000) check = textMatches(/.*确认授权即同意.*/).boundsInside(0, 0, device.width, device.height).findOne(8000) } if (!check) { console.log('无法找到入会按钮弹窗,加载失败') return false } if (check.indexInParent() == 2) { check = check.parent().child(1) } else { let anchor = textContains('*****').findOnce() check = anchor.parent().child(anchor.indexInParent() + 2) if (!check.bounds().top >= anchor.bounds().bottom) { console.log('使用第二种方法获取控件') let check1 = anchor.parent().children().findOne(filter(function (w) { if (w.className().match(/ImageView/) && w.bounds().top >= anchor.bounds().bottom) { return true } else { return false } })) if (!check1) { console.log('第二种方法也无法确认授权勾选框,失败。返回。') return false } else { check = check1 console.log('成功,继续') } } } console.log("最终[确认授权]前面选项框坐标为:", check.bounds()); let x = check.bounds().centerX() let y = check.bounds().centerY() console.log('检测是否有遮挡') let float = className('android.widget.ImageView') .filter(function (w) { let b = w.bounds() return b.left <= x && b.right >= x && b.top <= y && b.bottom >= y && b.centerX() != x && b.centerY() != y }).findOnce() if (float) { console.log('有浮窗遮挡,尝试移除') if (device.sdkInt >= 24) { gesture(1000, [float.bounds().centerX(), float.bounds().centerY()], [float.bounds().centerX(), y + float.bounds().height()]) console.log('已经进行移开操作,如果失败请反馈') } else { console.log('安卓版本低,无法自动移开浮窗,入会任务失败。至少需要安卓7.0。') return false } } else { console.log('未发现遮挡的浮窗,继续勾选') } console.log('即将勾选授权,自动隐藏控制台') sleep(500) console.hide() sleep(1000) click(x, y) sleep(500) console.show() console.log('准备点击入会按钮') let j = textMatches(/^确认授权(并加入店铺会员)*$|.*立即开通.*/).findOne(5000) if (!j) { console.log('无法找到入会按钮,失败') return false } click(j.bounds().centerX(), j.bounds().centerY()) sleep(1000) console.log('入会完成,返回') return true } } // 浏览商品和加购的任务,cart参数为是否加购的flag function itemTask(cart) { console.log('等待进入商品列表...') let anchor = textContains('当前页').findOne(20000) if (!anchor) { console.log('未能进入商品列表。') return false } sleep(2000) if (anchor.parent().childCount()==4) { console.log('任务重复完成,返回') return false } let items = textContains('.jpg!q70').find() for (let i = 0; i < items.length; i++) { console.log('浏览') let tmp = items[i].parent().parent() tmp.child(tmp.childCount() - 1).click() sleep(5000) console.log('返回') back() sleep(5000) let r = textContains('当前页').findOnce() if (!r) { back() sleep(5000) } if (i >= 4 - 1) { break } } return true } // 逛店任务 TODO: 618版本 function shopTask() { console.log('等待进入店铺列表...') let banner = textContains('喜欢').findOne(10000) if (!banner) { console.log('未能进入店铺列表。返回。') return false } let c = banner.text().match(/(\d)\/(\d*)/) if (!c) { c = 4 // 进行4次 } else { c = c[2] - c[1] } sleep(2000) console.log('进行', c, '次') let like = text('喜欢').boundsInside(1, 0, device.width, device.height).findOnce() if (!like) { console.log('未能找到喜欢按钮。返回。') return false } let bound = [like.bounds().centerX(), like.bounds().centerY()] console.log('喜欢按钮位于', bound) for (let i = 0; i < c; i++) { click(bound[0], bound[1]) console.log('浏览店铺页') sleep(8000) console.log('返回') back() sleep(5000) let r = textContains('喜欢').findOnce() if (!r) { back() sleep(5000) } } return true } // 参观任务 function viewTask() { console.log('进行参观任务') sleep(5000) console.log('参观任务直接返回') return true } // 品牌墙任务 TODO: 618版本 function wallTask() { console.log('进行品牌墙任务') sleep(3000) for (let i of [2, 3, 4, 5, 6]) { // 选5个 console.log('打开一个') textContains('!q70').boundsInside(100, 100, device.width, device.height).findOnce(i).click() sleep(5000) console.log('直接返回') back() let r = textContains('!q70').findOne(8000) if (!r) back() sleep(3000) } // console.log('返回顶部') // let root = textContains('到底了').findOnce().parent().parent() // root.child(root.childCount() - 2).click() console.log('品牌墙完成后重新打开任务列表') sleep(3000) openTaskList() return true } // 单个任务的function,自动进入任务、自动返回任务列表,返回boolean // TODO: 618 function doTask(tButton, tText, tTitle) { let clickFlag = tButton.click() let tFlag if (tButton.text() == '去领取') { tFlag = clickFlag // 打卡点击一次即可 return tFlag } if (tText.match(/品牌墙/) || tTitle.match(/品牌墙/)) { if (tTitle.match(/浏览更多权益/)) { console.log('简单品牌墙任务,等待10s') sleep(10000) return true } tFlag = wallTask() return tFlag // 品牌墙无需backToList,提前返回 } else if (tText.match(/浏览并关注.*s|浏览.*s/)) { console.log('进行', tText) tFlag = timeTask() } else if (tText.match(/累计浏览/)) { console.log('进行累计浏览任务') if (tText.match(/加购/)) { tFlag = itemTask(true) } else { tFlag = itemTask(false) } } else if (tText.match(/入会/)) { console.log('进行入会任务') tFlag = joinTask() } else if (tText.match(/浏览可得|浏览可获得|浏览并关注|晚会|参与/)) { if (tTitle.match(/种草城/)) { tFlag = shopTask() } else { tFlag = viewTask() } } else if (tText.match(/打卡|首页/)) { tFlag = clickFlag // 打卡点击一次即可 return tFlag } else if (tText.match(/组队/)) { console.log('等待组队任务') sleep(3000) if (findTextDescMatchesTimeout(/.*每做一次任务.*/, 1000)) { console.log('当前仍在任务列表,说明已经完成任务且领取奖励,返回') return true } else { if (textContains('队伍快递箱').findOne(10000)) { console.log('进入到组队页面,返回') backToList() console.log('等待领取奖励') sleep(2000) tFlag = tButton.click() sleep(2000) return tFlag } else { console.log('未能进入组队') if (findTextDescMatchesTimeout(/.*每做一次任务.*/, 1000)) { console.log('当前仍在任务列表,返回') return true } else { console.log('组队任务未检测到页面标识,视为已完成') tFlag = false } } } } else { console.log('未知任务类型,默认为浏览任务', tText) tFlag = timeTask() } backToList() return tFlag } function signTask() { console.log('尝试关闭弹窗') let anchor = textMatches(/\+\d*快递箱/).findOnce(); for (let i = 0; i < 5 && anchor; i++) { try { let tmp = anchor.parent().parent().child(0) if (!tmp.clickable()) { tmp = anchor.parent().parent().parent().child(0) } tmp.click() console.log('关闭') sleep(1000) anchor = textMatches(/\+\d*快递箱/).findOnce() } catch (err) { pass } } anchor = text('记录').findOne(5000) if (!anchor) { console.log('未能定位,签到失败') quit() } let sign if (anchor.indexInParent() < 3) { anchor = anchor.parent() } sign = anchor.parent().child(10) if (!sign.clickable()) { sign = anchor.parent().child(11) } sign.click() sleep(3000) anchor = text('提醒我每天签到').findOne(5000) if (!anchor) { console.log('未找到签到按钮') return false } anchor = anchor.parent().parent() sign = anchor.child(anchor.childCount() - 2) console.log('点击签到') return sign.click() } // 领取快递箱 function havestCoin() { console.log('准备领取自动积累的快递箱') let h = textMatches(/.*点击领取.*|.*后存满.*/).findOne(5000) if (h) { h.click() console.log('领取成功') sleep(8000) } else { console.log('未找到快递箱控件,领取失败') } } // 关闭主页的弹窗 function closePop() { let anchor = text('已放入首页>记录').findOnce() if (!anchor) { console.log('寻找关闭弹窗按钮失败') return false } anchor = anchor.parent() return anchor.child(anchor.childCount()-2).click() } let startCoin = null // 音量键需要 // 全局try catch,应对无法显示报错 try { if (autoOpen) { openAndInto() console.log('等待活动页面加载') if (!findTextDescMatchesTimeout(/.*快递箱.*/, 8000)) { console.log('未能进入活动,请重新运行!') quit() } console.log('成功进入活动,向下滑动一段以保证控件全部出现') sleep(2000) scrollDown(); openTaskList(); } else { alert('请关闭弹窗后立刻手动打开京东App进入活动页面,并打开任务列表', '限时30秒') console.log('请手动打开京东App进入活动页面,并打开任务列表') if (!findTextDescMatchesTimeout(/.*每做一次任务.*|攻略/, 30000)) { console.log('未能进入活动,请重新运行!') quit() } console.log('成功进入活动') } sleep(5000) try { console.log('获取初始快递箱数量') startCoin = getCoin() console.log('当前共有' + startCoin + '快递箱') } catch (err) { console.log('获取快递箱失败,跳过', err) } // havestCoin() // 完成所有任务的循环 while (true) { let [taskButton, taskText, taskCount, taskTitle] = getTaskByText() if (!taskButton) { // console.log('领取累计奖励') // textContains('去领取').find().forEach(function (e, i) { // console.log('领取第' + (i + 1) + '个累计奖励') // e.click() // sleep(2000) // }) // havestCoin() // console.log('最后进行签到任务') // let signT = signTask() let endCoin = null try { console.log('获取结束快递箱数量') endCoin = getCoin() console.log('当前共有' + endCoin + '快递箱') } catch (err) { console.log('获取快递箱失败,跳过', err) } console.log('没有可自动完成的任务了,退出。') console.log('互动任务、下单任务需要手动完成。') if (startCoin && endCoin) { console.log('本次运行获得' + (endCoin - startCoin) + '快递箱') } else { console.log('本次运行获得快递箱无法计算,具体原因请翻阅日志。') } alert('任务已完成', '别忘了在脚本主页领取618红包!') // if (!signT) { // alert('本次签到失败', '请手动签到避免漏签(活动页右上角)') // } // alert('任务已完成', '互动任务手动完成之后还会有新任务,建议做完互动二次运行脚本') quit() } if (taskText.match(/品牌墙/) || taskTitle.match(/种草城/)) { // 品牌墙0/3只需要一次完成 taskCount = 1 } // 根据taskCount进行任务,一类任务一起完成,完成后刷新任务列表 console.log('进行' + taskCount + '次“' + taskText + '”类任务') for (let i = 0; i < taskCount; i++) { console.log('第' + (i + 1) + '次') let taskFlag = doTask(taskButton, taskText, taskTitle) if (text('已放入首页>记录').exists()) { console.log('关闭奖励弹窗') closePop() sleep(3000) } if (taskFlag) { console.log('完成,进行下一个任务') } else { console.log('任务失败,尝试重新打开任务列表获取任务') break // 直接退出,无需在此调用reopen } } console.log('重新打开任务列表获取任务') reopenTaskList() } } catch (err) { device.cancelKeepingAwake() if (err.toString() != 'JavaException: com.stardust.autojs.runtime.exception.ScriptInterruptedException: null') { console.error(err) startCoin && console.log('本次任务开始时有' + startCoin + '快递箱') } showVersion() }