• 2022年1111/双11淘宝/天猫/京东任务自动助手,分享源码学习


    下载地址:助手https://wwc.lanzouv.com/b01cfbrbi

    自动完成双11天猫喵币/京东任务穿行寻宝任务,领取奖励!

     

    1. if (!auto.service) {
    2. toast('无障碍服务未启动!退出!')
    3. exit()
    4. }
    5. console.show()
    6. function getSetting() {
    7. let indices = []
    8. autoOpen && indices.push(0)
    9. autoMute && indices.push(1)
    10. autoJoin && indices.push(2)
    11. indices.push(3)
    12. let settings = dialogs.multiChoice('任务设置', ['自动打开京东进入活动。多开或任务列表无法自动打开时取消勾选', '自动调整媒体音量为0。以免直播任务发出声音,首次选择需要修改系统设置权限', '自动完成入会任务。京东将授权手机号给商家,日后可能会收到推广短信', '此选项用于保证选择的处理,勿动!'], indices)
    13. if (settings.length == 0) {
    14. toast('取消选择,任务停止')
    15. exit()
    16. }
    17. if (settings.indexOf(0) != -1) {
    18. storage.put('autoOpen', true)
    19. autoOpen = true
    20. } else {
    21. storage.put('autoOpen', false)
    22. autoOpen = false
    23. }
    24. if (settings.indexOf(1) != -1) {
    25. storage.put('autoMute', true)
    26. autoMute = true
    27. } else {
    28. storage.put('autoMute', false)
    29. autoMute = false
    30. }
    31. if (settings.indexOf(2) != -1) {
    32. storage.put('autoJoin', true)
    33. autoJoin = true
    34. } else {
    35. storage.put('autoJoin', false)
    36. autoJoin = false
    37. }
    38. }
    39. let storage = storages.create("jd_task");
    40. let autoOpen = storage.get('autoOpen', true)
    41. let autoMute = storage.get('autoMute', true)
    42. let autoJoin = storage.get('autoJoin', true)
    43. getSetting()
    44. if (autoMute) {
    45. try {
    46. device.setMusicVolume(0)
    47. toast('成功设置媒体音量为0')
    48. } catch (err) {
    49. alert('首先需要开启权限,请开启后再次运行脚本')
    50. exit()
    51. }
    52. }
    53. console.log('开始完成京东任务...')
    54. console.log('按音量下键停止')
    55. device.keepScreenDim(30 * 60 * 1000) // 防止息屏30分钟
    56. // 自定义取消亮屏的退出方法
    57. function quit() {
    58. device.cancelKeepingAwake()
    59. exit()
    60. }
    61. // 监听音量下键
    62. function registerKey() {
    63. try {
    64. events.observeKey()
    65. } catch (err) {
    66. console.log('监听音量键停止失败,应该是无障碍权限出错,请关闭软件后台任务重新运行。')
    67. console.log('如果还是不行可以重启手机尝试。')
    68. quit()
    69. }
    70. events.onKeyDown('volume_down', function (event) {
    71. console.log('京东任务脚本停止了')
    72. console.log('请手动切换回主页面')
    73. startCoin && console.log('本次任务开始时有' + startCoin + '金币')
    74. quit()
    75. })
    76. }
    77. threads.start(registerKey)
    78. // 自定义一个findTextDescMatchesTimeout
    79. function findTextDescMatchesTimeout(reg, timeout) {
    80. let c = 0
    81. while (c < timeout / 50) {
    82. let result = textMatches(reg).findOnce() || descMatches(reg).findOnce()
    83. if (result) return result
    84. sleep(50)
    85. c++
    86. }
    87. return null
    88. }
    89. // 打开京东进入活动
    90. function openAndInto() {
    91. console.log('正在打开京东App...')
    92. if (!launch('com.jingdong.app.mall')) {
    93. console.log('可能未安装京东App')
    94. }
    95. sleep(2000)
    96. console.log('进入活动页面')
    97. app.startActivity({
    98. action: "VIEW",
    99. data: 'openApp.jdMobile://virtual?params={"category":"jump","action":"to","des":"m","sourceValue":"JSHOP_SOURCE_VALUE","sourceType":"JSHOP_SOURCE_TYPE","url":"https://u.jd.com/kIaMhxS","M_sourceFrom":"mxz","msf_type":"auto"}'
    100. })
    101. }
    102. // 获取金币数量
    103. function getCoin() {
    104. let anchor = text('消耗').findOne(5000)
    105. if (!anchor) {
    106. console.log('找不到消耗控件')
    107. return false
    108. }
    109. let coin = anchor.parent().parent().parent().parent().child(1).text()
    110. if (coin) {
    111. return parseInt(coin)
    112. } else {
    113. coin = anchor.parent().parent().parent().parent().child(2).text() // 有可能中间插了个控件
    114. if (coin) {
    115. return parseInt(coin)
    116. } else {
    117. return false
    118. }
    119. }
    120. }
    121. // 打开任务列表
    122. function openTaskList() {
    123. console.log('打开任务列表')
    124. let taskListButtons = text('消耗').findOne(20000)
    125. if (!taskListButtons) {
    126. console.log('未能打开任务列表,请关闭京东重新运行!')
    127. quit()
    128. }
    129. taskListButtons = taskListButtons.parent().parent().parent().parent().children()
    130. let taskListButton = taskListButtons.findOne(boundsInside(device.width/2, 0, device.width, device.height).clickable())
    131. if (!taskListButton || !taskListButton.clickable()) {
    132. console.log('无法找到任务列表控件')
    133. quit()
    134. }
    135. taskListButton.click()
    136. console.log('等待任务列表')
    137. if (!findTextDescMatchesTimeout(/累计任务奖励/, 5000)) {
    138. console.log('似乎没能打开任务列表,重试')
    139. taskListButton.click()
    140. }
    141. if (!findTextDescMatchesTimeout(/累计任务奖励/, 10000)) {
    142. console.log('似乎没能打开任务列表,退出!')
    143. console.log('如果已经打开而未检测到,请删除101版本及以上的webview或使用国内应用市场版京东尝试。')
    144. quit()
    145. }
    146. }
    147. // 关闭任务列表
    148. function closeTaskList() {
    149. console.log('关闭任务列表')
    150. let renwu = findTextDescMatchesTimeout(/.*做任务.*/, 5000)
    151. if (!renwu) {
    152. console.log('无法找到任务奖励标识')
    153. return false
    154. }
    155. let closeBtn = renwu.parent().parent().parent().child(0)
    156. return closeBtn.click()
    157. }
    158. // 重新打开任务列表
    159. function reopenTaskList() {
    160. closeTaskList()
    161. sleep(3000)
    162. openTaskList()
    163. sleep(5000)
    164. }
    165. // 获取未完成任务,根据数字标识,返回任务按钮、任务介绍、任务数量(数组)
    166. function getTaskByText() {
    167. let tButton = null,
    168. tText = null,
    169. tCount = 0,
    170. tTitle = null
    171. console.log('寻找未完成任务...')
    172. let taskButtons = textMatches(/去完成|去领取|去打卡/).find()
    173. if (!taskButtons.empty()) { // 如果找不到任务,直接返回
    174. for (let i = 0; i < taskButtons.length; i++) {
    175. let button = taskButtons[i]
    176. // if (tButton.text() == '去领取') {
    177. // console.log('领取奖励')
    178. // tButton.click()
    179. // sleep(500)
    180. // continue
    181. // }
    182. let tmp = button.parent().child(button.indexInParent() - 1)
    183. tTitle = tmp.child(0).text()
    184. let r = tTitle.match(/(\d*)\/(\d*)/)
    185. if (!r) continue
    186. tCount = (r[2] - r[1])
    187. console.log(tTitle, tCount)
    188. if (tCount) { // 如果数字相减不为0,证明没完成
    189. tText = tmp.child(1).text()
    190. if (!autoJoin && tText.match(/成功入会/)) continue
    191. if (tTitle.match(/下单|小程序/)) continue
    192. tButton = button
    193. break
    194. }
    195. }
    196. } else {
    197. console.log('任务提示未找到')
    198. }
    199. return [tButton, tText, tCount, tTitle]
    200. }
    201. // 返回任务列表并检查是否成功,不成功重试一次,带有延时
    202. function backToList() {
    203. sleep(500)
    204. back()
    205. for (let i = 0; i < 3; i++) { // 尝试返回3次
    206. if (!findTextDescMatchesTimeout(/累计任务奖励/, 5000)) {
    207. console.log('返回失败,重试返回')
    208. sleep(2000)
    209. back()
    210. continue
    211. } else {
    212. break
    213. }
    214. }
    215. sleep(3000)
    216. }
    217. // 浏览n秒的任务
    218. function timeTask() {
    219. console.log('等待浏览任务完成...')
    220. if (textMatches(/.*滑动浏览.*[^可]得.*/).findOne(10000)) {
    221. console.log('模拟滑动')
    222. swipe(device.width / 2, device.height - 200, device.width / 2 + 20, device.height - 500, 500)
    223. }
    224. let c = 0
    225. while (c < 40) { // 0.5 * 40 = 20 秒,防止死循环
    226. if ((textMatches(/获得.*?金币/).exists() || descMatches(/获得.*?金币/).exists())) // 等待已完成出现
    227. break
    228. if ((textMatches(/已浏览/).exists() || descMatches(/已浏览/).exists())) { // 失败
    229. console.log('上限,返回刷新任务列表')
    230. return false
    231. }
    232. // 弹窗处理
    233. let pop = text('升级开卡会员领好礼')
    234. if (pop.exists()) {
    235. pop.findOnce().parent().parent().child(2).click()
    236. console.log('关闭会员弹窗')
    237. }
    238. sleep(500)
    239. c++
    240. }
    241. if (c > 39) {
    242. console.log('未检测到任务完成标识。')
    243. return false
    244. }
    245. console.log('已完成,准备返回')
    246. return true
    247. }
    248. // 入会任务
    249. function joinTask() {
    250. let check = textMatches(/.*确认授权即同意.*|.*我的特权.*|.*立即开卡.*|.*解锁全部会员福利.*/).findOne(8000)
    251. if (!check) {
    252. console.log('无法找到入会按钮,判定为已经入会')
    253. return true
    254. } else if (check.text().match(/我的特权/)) {
    255. console.log('已经入会,返回')
    256. return true
    257. } else {
    258. sleep(2000)
    259. if (check.text().match(/.*立即开卡.*|.*解锁全部会员福利.*|授权解锁/)) {
    260. let btn = check.bounds()
    261. console.log('即将点击开卡/解锁福利,自动隐藏控制台')
    262. sleep(500)
    263. console.hide()
    264. sleep(500)
    265. click(btn.centerX(), btn.centerY())
    266. sleep(500)
    267. console.show()
    268. sleep(5000)
    269. check = textMatches(/.*确认授权即同意.*/).boundsInside(0, 0, device.width, device.height).findOne(8000)
    270. }
    271. if (!check) {
    272. console.log('无法找到入会按钮弹窗,加载失败')
    273. return false
    274. }
    275. // text("instruction_icon") 全局其实都只有一个, 保险起见, 使用两个parent来限定范围
    276. let checks = check.parent().parent().find(text("instruction_icon"));
    277. if (checks.size() > 0) {
    278. // 解决部分店铺(欧莱雅)开卡无法勾选 [确认授权] 的问题
    279. check = checks.get(0);
    280. } else {
    281. if (check.indexInParent() >= 6) {
    282. check = check.parent().child(5)
    283. } else if (check.text() == '确认授权即同意') {
    284. check = check.parent().child(0)
    285. } else {
    286. check = check.parent().parent().child(5)
    287. }
    288. }
    289. check = check
    290. log("最终[确认授权]前面选项框坐标为:", check);
    291. let x = check.bounds().centerX()
    292. let y = check.bounds().centerY()
    293. console.log('检测是否有遮挡')
    294. let float = className('android.widget.ImageView')
    295. .filter(function (w) {
    296. let b = w.bounds()
    297. return b.left <= x && b.right >= x && b.top <= y && b.bottom >= y && b.centerX() != x && b.centerY() != y
    298. }).findOnce()
    299. if (float) {
    300. console.log('有浮窗遮挡,尝试移除')
    301. if (device.sdkInt >= 24) {
    302. gesture(1000, [float.bounds().centerX(), float.bounds().centerY()], [float.bounds().centerX(), y + float.bounds().height()])
    303. console.log('已经进行移开操作,如果失败请反馈')
    304. } else {
    305. console.log('安卓版本低,无法自动移开浮窗,入会任务失败。至少需要安卓7.0。')
    306. return false
    307. }
    308. } else {
    309. console.log('未发现遮挡的浮窗,继续勾选')
    310. }
    311. console.log('即将勾选授权,自动隐藏控制台')
    312. sleep(500)
    313. console.hide()
    314. sleep(1000)
    315. click(x, y)
    316. sleep(500)
    317. console.show()
    318. console.log('准备点击入会按钮')
    319. let j = textMatches(/^确认授权(并加入店铺会员)*$|.*立即开通.*/).findOne(5000)
    320. if (!j) {
    321. console.log('无法找到入会按钮,失败')
    322. return false
    323. }
    324. click(j.bounds().centerX(), j.bounds().centerY())
    325. sleep(1000)
    326. console.log('入会完成,返回')
    327. return true
    328. }
    329. }
    330. // 浏览商品和加购的任务,cart参数为是否加购的flag
    331. function itemTask(cart) {
    332. console.log('等待进入商品列表...')
    333. if (!textContains('当前页').findOne(10000)) {
    334. console.log('未能进入商品列表。')
    335. return false
    336. }
    337. sleep(2000)
    338. let items = textContains('.jpg!q70').find()
    339. for (let i = 0; i < items.length; i++) {
    340. if (cart) {
    341. console.log('加购并浏览')
    342. let tmp = items[i].parent().parent()
    343. tmp.child(tmp.childCount() - 1).click()
    344. } else {
    345. console.log('浏览商品页')
    346. items[i].parent().parent().child(4).click()
    347. }
    348. sleep(5000)
    349. console.log('返回')
    350. back()
    351. sleep(5000)
    352. let r = textContains('.jpg!q70').findOnce()
    353. if (!r) {
    354. back()
    355. sleep(5000)
    356. }
    357. if (i >= 4 - 1) {
    358. break
    359. }
    360. }
    361. return true
    362. }
    363. // 逛店任务
    364. function shopTask() {
    365. console.log('等待进入店铺列表...')
    366. let banner = textContains('喜欢').findOne(10000)
    367. if (!banner) {
    368. console.log('未能进入店铺列表。返回。')
    369. return false
    370. }
    371. let c = banner.text().match(/(\d)\/(\d*)/)
    372. if (!c) {
    373. c = 4 // 进行4次
    374. } else {
    375. c = c[2] - c[1]
    376. }
    377. sleep(2000)
    378. console.log('进行', c, '次')
    379. let like = textContains('喜欢').boundsInside(1, 0, device.width, device.height).findOnce()
    380. if (!like) {
    381. console.log('未能找到喜欢按钮。返回。')
    382. return false
    383. }
    384. let bound = [like.bounds().centerX(), like.bounds().centerY()]
    385. console.log('喜欢按钮位于', bound)
    386. for (let i = 0; i < c; i++) {
    387. click(bound[0], bound[1])
    388. console.log('浏览店铺页')
    389. sleep(8000)
    390. console.log('返回')
    391. back()
    392. sleep(5000)
    393. let r = textContains('喜欢').findOnce()
    394. if (!r) {
    395. back()
    396. sleep(5000)
    397. }
    398. }
    399. return true
    400. }
    401. // 参观任务
    402. function viewTask() {
    403. console.log('进行参观任务')
    404. sleep(5000)
    405. console.log('参观任务直接返回')
    406. return true
    407. }
    408. // 品牌墙任务
    409. function wallTask() {
    410. console.log('进行品牌墙任务')
    411. sleep(3000)
    412. for (let i of [2, 3, 4, 5, 6]) { // 选5个
    413. console.log('打开一个')
    414. textContains('!q70').boundsInside(0, 0, device.width, device.height).findOnce(i).click()
    415. sleep(5000)
    416. console.log('直接返回')
    417. back()
    418. let r = textContains('!q70').findOne(8000)
    419. if (!r) back()
    420. sleep(3000)
    421. }
    422. // console.log('返回顶部')
    423. // let root = textContains('到底了').findOnce().parent().parent()
    424. // root.child(root.childCount() - 2).click()
    425. console.log('品牌墙完成后重新打开任务列表')
    426. sleep(3000)
    427. openTaskList()
    428. return true
    429. }
    430. // 单个任务的function,自动进入任务、自动返回任务列表,返回boolean
    431. function doTask(tButton, tText, tTitle) {
    432. let clickFlag = tButton.click()
    433. let tFlag
    434. if (tButton.text() == '去领取') {
    435. tFlag = clickFlag // 打卡点击一次即可
    436. return tFlag
    437. }
    438. if (tText.match(/浏览并关注.*s|浏览.*s/)) {
    439. console.log('进行', tText)
    440. tFlag = timeTask()
    441. } else if (tText.match(/累计浏览/)) {
    442. console.log('进行累计浏览任务')
    443. if (tText.match(/加购/)) {
    444. tFlag = itemTask(true)
    445. } else {
    446. tFlag = itemTask(false)
    447. }
    448. } else if (tText.match(/入会/)) {
    449. console.log('进行入会任务')
    450. tFlag = joinTask()
    451. } else if (tText.match(/浏览可得|浏览并关注|晚会/)) {
    452. if (tTitle.match(/种草城/)) {
    453. tFlag = shopTask()
    454. } else {
    455. tFlag = viewTask()
    456. }
    457. } else if (tText.match(/品牌墙/)) {
    458. if (tTitle.match(/浏览更多权益/)) {
    459. console.log('简单品牌墙任务,等待10s')
    460. sleep(10000)
    461. return true
    462. }
    463. tFlag = wallTask()
    464. return tFlag // 品牌墙无需backToList,提前返回
    465. } else if (tText.match(/打卡|首页/)) {
    466. tFlag = clickFlag // 打卡点击一次即可
    467. return tFlag
    468. } else if (tText.match(/组队/)) {
    469. console.log('等待组队任务')
    470. sleep(3000)
    471. if (findTextDescMatchesTimeout(/累计任务奖励/, 1000)) {
    472. console.log('当前仍在任务列表,说明已经完成任务且领取奖励,返回')
    473. return true
    474. } else {
    475. if (textContains('我的金币').findOne(10000)) {
    476. console.log('进入到组队页面,返回')
    477. backToList()
    478. console.log('等待领取奖励')
    479. sleep(2000)
    480. tFlag = tButton.click()
    481. sleep(2000)
    482. return tFlag
    483. } else {
    484. console.log('未能进入组队')
    485. console.log('组队任务失败,避免卡死,退出')
    486. quit()
    487. }
    488. }
    489. } else {
    490. console.log('未知任务类型,默认为浏览任务', tText)
    491. tFlag = timeTask()
    492. }
    493. backToList()
    494. return tFlag
    495. }
    496. function signTask() {
    497. let anchor = className('android.view.View').filter(function (w) {
    498. return w.clickable() && (w.text() == '去使用奖励' || w.desc() == '去使用奖励')
    499. }).findOne(5000)
    500. if (!anchor) {
    501. console.log('未找到使用奖励按钮,签到失败')
    502. return false
    503. }
    504. let anchor_index = anchor.indexInParent()
    505. let sign = anchor.parent().child(anchor_index + 2) // 去使用的后两个
    506. sign.click()
    507. sleep(3000)
    508. sign = textMatches(/.*点我签到.*|.*明天继续来.*/).findOne(5000)
    509. if (!sign) {
    510. console.log('未找到签到按钮')
    511. return false
    512. }
    513. if (sign.text().match(/明天继续来/)) {
    514. console.log('已经签到')
    515. } else {
    516. sign.click()
    517. }
    518. return true
    519. }
    520. // 领取金币
    521. function havestCoin() {
    522. console.log('准备领取自动积累的金币')
    523. let h = descMatches(/.*领取金币.*|.*后满.*/).findOne(5000)
    524. if (h) {
    525. h.click()
    526. console.log('领取成功')
    527. } else { console.log('未找到金币控件,领取失败') }
    528. }
    529. let startCoin = null // 音量键需要
    530. // 全局try catch,应对无法显示报错
    531. try {
    532. if (autoOpen) {
    533. openAndInto()
    534. console.log('等待活动页面加载')
    535. if (!findTextDescMatchesTimeout(/.*开心愿奖.*/, 8000)) {
    536. console.log('未能进入活动,请重新运行!')
    537. quit()
    538. }
    539. console.log('成功进入活动')
    540. sleep(2000)
    541. openTaskList();
    542. } else {
    543. alert('请关闭弹窗后立刻手动打开京东App进入活动页面,并打开任务列表', '限时30秒')
    544. console.log('请手动打开京东App进入活动页面,并打开任务列表')
    545. if (!findTextDescMatchesTimeout(/累计任务奖励|互动攻略/, 30000)) {
    546. console.log('未能进入活动,请重新运行!')
    547. quit()
    548. }
    549. console.log('成功进入活动')
    550. }
    551. sleep(5000)
    552. try {
    553. console.log('获取初始金币数量')
    554. startCoin = getCoin()
    555. console.log('当前共有' + startCoin + '金币')
    556. } catch (err) {
    557. console.log('获取金币失败,跳过', err)
    558. }
    559. sleep(1000)
    560. havestCoin()
    561. sleep(1000)
    562. // 完成所有任务的循环
    563. while (true) {
    564. let [taskButton, taskText, taskCount, taskTitle] = getTaskByText()
    565. if (!taskButton) {
    566. console.log('领取累计奖励')
    567. textContains('去领取').find().forEach(function (e, i) {
    568. console.log('领取第' + (i + 1) + '个累计奖励')
    569. e.click()
    570. sleep(2000)
    571. })
    572. sleep(1000)
    573. havestCoin()
    574. sleep(1000)
    575. console.log('最后进行签到任务')
    576. signTask()
    577. let endCoin = null
    578. try {
    579. console.log('获取结束金币数量')
    580. endCoin = getCoin()
    581. console.log('当前共有' + endCoin + '金币')
    582. } catch (err) {
    583. console.log('获取金币失败,跳过', err)
    584. }
    585. console.log('没有可自动完成的任务了,退出。')
    586. console.log('互动任务、下单任务需要手动完成。')
    587. if (startCoin && endCoin) {
    588. console.log('本次运行获得' + (endCoin - startCoin) + '金币')
    589. } else {
    590. console.log('本次运行获得金币无法计算,具体原因请翻阅日志。')
    591. }
    592. // alert('任务已完成', '别忘了在脚本主页领取年货节红包!')
    593. alert('任务已完成', '互动任务手动完成之后还会有新任务,建议做完互动二次运行脚本')
    594. quit()
    595. }
    596. if (taskText.match(/品牌墙/)) { // 品牌墙0/3只需要一次完成
    597. taskCount = 1
    598. }
    599. // 根据taskCount进行任务,一类任务一起完成,完成后刷新任务列表
    600. console.log('进行' + taskCount + '次“' + taskText + '”类任务')
    601. for (let i = 0; i < taskCount; i++) {
    602. console.log('第' + (i + 1) + '次')
    603. let taskFlag = doTask(taskButton, taskText, taskTitle)
    604. if (taskFlag) {
    605. console.log('完成,进行下一个任务')
    606. } else {
    607. console.log('任务失败,尝试重新打开任务列表获取任务')
    608. break // 直接退出,无需在此调用reopen
    609. }
    610. }
    611. console.log('重新打开任务列表获取任务')
    612. reopenTaskList()
    613. }
    614. } catch (err) {
    615. device.cancelKeepingAwake()
    616. if (err.toString() != 'JavaException: com.stardust.autojs.runtime.exception.ScriptInterruptedException: null') {
    617. console.error(err)
    618. startCoin && console.log('本次任务开始时有' + startCoin + '金币')
    619. }
    620. }

  • 相关阅读:
    线程池处理异常的方法
    细胞膜包裹精氨酸脱亚胺酶脂质纳米粒/融合细胞膜包裹尿酸酶/过氧化氢酶脂质纳米粒的研究
    Python Web开发(三):HTTP请求的url路由
    螺旋折线(找规律 + 准确取点优化分析 + 普通思路)【包含详细的思考过程】
    SAP 批导长文本字段自动和手动换行
    OpenCV4 :并行计算cv::parallel_for_
    asp毕业设计——基于asp+access的在线考试系统设计与实现(毕业论文+程序源码)——在线考试系统
    TCP通信流程详解
    2.Mybatis XML 方法的基本用法
    开发一个商城需要多少钱 做一个电商网站大概多少钱
  • 原文地址:https://blog.csdn.net/weixin_45504660/article/details/127441652