简介:2021年发布的AutoJS脚本合集收录了近三千个可直接运行的JS脚本,覆盖安卓自动化测试、群控操作和个人效率提升等场景,适合从零基础到进阶开发的各类用户。压缩包为zip格式,仅7.09MB,全部脚本均为.js文件,轻量易携、便于按需提取。已有4438人学习/下载,是社区内较热门的AutoJS参考资料。实例涵盖UI自动化、数据解析、文件读写、定时任务、网络请求、交互弹窗及系统API调用等高频功能,既能独立复用也能组合改造;配合作者梳理的学习路径,用户可从阅读、模仿过渡到自行编写,逐步掌握点击、滑动、读取屏幕信息、定时启动应用等技能,搭建个人脚本库。这份资料特别适合需要系统学习安卓自动化或快速解决重复操作的人,目录结构清晰、可直接导入AutoJS运行,兼顾学习与二次开发价值。
1. 接近三千个 AutoJS 实例到底意味着什么,以及你该怎么挑
AutoJS 在 2021 年迎来了一波脚本爆发,各类 QQ 群、网盘和 GitHub 仓库里出现了大量打包好的脚本实例,少说几百,多则上千。标题里说“接近三千个实例脚本”并不夸张,很多合集是从 QQ 群聊天记录、贴吧帖子、网盘共享和早期论坛里汇总来的,去重前确实能凑到两三千这个量级。但这批资源的核心价值不在“数量”,而在“样本覆盖度”:从悬浮窗权限申请、控件文本匹配、坐标点击、图片找色,到 WebView 抓包、HTTP 请求、文件读写、定时任务、Pro 版加密运行,几乎把 AutoJS 的 API 都摸了一遍。真正看过三千个脚本的人,基本都能回答一个问题:AutoJS 的脚本体系里,哪些 API 是高频的、哪些写法是迟早会被废弃的、哪些坑是绕不过去的。
这篇面向的读者有两类。一类是刚开始接触 AutoJS、手里有一大堆脚本但不知道从哪个开始读的新手,另一类是已经写过几十个脚本、想从大样本里提炼通用做法的熟手。无论哪一类,核心思路都一样:先建立对脚本结构的判断力,再决定怎么跑、怎么改、怎么沉淀。三千这个数字不是用来膜拜的,而是用来做统计分析的。
2. 从三千个实例里看懂 AutoJS 脚本的三种基本结构
2.1 脚本的“入口与生命周期”是判断脚本质量的第一步
拿到一个陌生实例,不要先看中间的循环和点击逻辑,先找入口函数和生命周期。AutoJS 脚本的入口有三种常见形态。第一种是纯顺序执行,脚本从上往下跑,跑完就结束,这类脚本最简单,适合一次性任务,例如解锁屏幕后打开某个应用再执行截图。第二种是ui入口,顶部有"ui";声明,配合ui.layout()使用,这类脚本通常带界面,会阻塞在ui.run()回调里,适合做带按钮和输入框的工具。第三种是setInterval或while (true)组成的长驻循环,配合engines.myEngine()和threads模块实现后台运行,这类脚本往往需要配套悬浮窗来控制启停。
判断实例属于哪一种,最直接的方法是看前五行的关键字。通常前五行会出现"ui";、auto();、requestScreenCapture();、setInterval(或者events.observeNotification()。这三种形态对应不同的使用场景:顺序执行的一次性脚本适合手动点击运行,带 UI 的脚本适合给不太熟悉 AutoJS 的人用,长驻循环的脚本适合放在自动驾驶场景里挂机。很多 2021 年的合集会把这三种混在一个文件包里,所以第一步先给每个脚本分类,后面才知道该配什么权限、该不该加防休眠代码。
2.2 控件型、坐标型、混合型的识别依据
AutoJS 实例的绝大多数代码逻辑都围绕“找到目标”这件事展开。找目标有三种路径:控件树、坐标、图像。控件型脚本的核心调用是text("xxx").findOne()、desc("xxx").findOne()、className("xxx").findOne(),它们的共同前提是页面元素可以被无障碍服务读取。坐标型脚本的核心是click(x, y)、swipe(x1, y1, x2, y2, duration),这类脚本不依赖控件树,只看分辨率,因此在 2021 年的合集里通常都带了分辨率判断。混合型脚本则是在控件查找失败时回退到坐标点击,用try...catch包裹findOne()的调用,再在 catch 分支里执行坐标点击。
一眼识别一个脚本属于哪种类型,就看click(的实参是变量还是常量。如果click()里传的是bounds().centerX()这类从控件对象取出的值,那就是控件型;如果传的是click(540, 1200)这样的字面量,那就是坐标型。实践中坐标型脚本最容易翻车,因为分辨率一变就可能整体偏掉。所以我一般遇到坐标型实例,会先看脚本开头有没有顺便做分辨率适配,如果没有,就要做好每换一台设备就手改一遍的心理准备。
2.3 一个典型挂机脚本应该具备的模块拆分
很多 2021 年的热门实例其实是“半成品模板”,它们美其名曰是脚本,实际就是一套可以来回改的通用框架。一个合格的 AutoJS 挂机脚本,至少应该包含以下几个模块:
auto(); // 申请无障碍服务并等待用户开启 requestScreenCapture(); // 申请截图权限,用于找色或 OCR // 配置区:根据设备环境调整的参数 var config = { width: device.width, height: device.height, scale: device.width / 1080, // 以 1080p 为基准的缩放系数 targetApp: "com.example.app", interval: 3000 }; // 入口函数:循环体 + 异常兜底 function main() { while (true) { try { if (!isAppFront()) { launchApp(); // 如果后台了就先拉起来 } doTask(); // 具体的任务逻辑 } catch (e) { console.error("任务执行失败: " + e); } sleep(config.interval); } } // 任务逻辑函数 function doTask() { var target = text("开始").findOne(2000); if (target) { target.click(); } } function isAppFront() { return currentPackage() == config.targetApp; } function launchApp() { app.launch(config.targetApp); sleep(1500); } main();这段代码是把挂机脚本拆成了四个部分:配置区、入口函数、任务函数、环境判断函数。配置区的好处是换了设备不用全文替换坐标,只要改scale或者直接改width/height即可;入口函数里的try...catch是防止单次任务报错导致整个脚本退出,这在长时间运行时非常重要;findOne(2000)里的 2000 是超时时间,单位毫秒,意思是如果 2 秒内找不到就抛出异常,由try...catch兜住。
这里要特别说scale这个变量的作用。很多坐标型实例直接用device.width / 1080作为缩放系数,然后在点击时写click(100 * scale, 200 * scale),这样在 1080 x 2400 和 1440 x 3200 的设备上可以做到近似适配。但要注意,这只是等比缩放,如果目标应用的控件是居中布局,缩放效果还凑合,如果是左对齐或右对齐的布局,等比缩放就会和实际位置出现偏差。所以更可靠的做法是,优先用控件型选择器,只有findOne()超时了才回退到坐标点击。
3. 把“接近三千个脚本”变成可控样本:筛选、批量解析与去重
3.1 按关键 API 调用频率做初筛
面对三千个脚本,人肉逐个翻是行不通的。最合理的做法是用脚本去扫脚本。常规思路是写一个 Node.js 或 Python 脚本,把.js文件全文读进来,统计高频调用的 API 名称出现的次数。这样几分钟就能得出一个词频表,排序后立刻就能看出这个合集里哪些 API 是主导。
grep -h -o -E "text|desc|className|id|bounds|click|swipe|scroll|setText|findOne|findOnce|waitFor|exists|press|longClick" *.js | sort | uniq -c | sort -rn上面这行命令在 Linux/macOS 的终端里直接可用。grep -h表示不要输出文件名,-o表示只输出匹配到的部分,-E使用扩展正则;sort先按词排序,uniq -c统计词频,最后的sort -rn按出现次数降序排列。如果是在 Windows 上,可以用 Git Bash 或者 WSL 跑同样的命令,也可以直接用 PowerShell 里的Select-String写等价逻辑。
统计结果出来以后,会发现几个事实。比如click和findOne几乎一定排在最前面,这说明坐标点击和控件查找是 AutoJS 的两大支柱型操作;如果requestScreenCapture的词频也很高,说明这个合集里有不少找色脚本,那就还需要准备找色的环境(模拟器要开截图权限);如果threads和setInterval出现频率低,说明这个合集里真正意义上的长驻后台脚本占比不大,多数是跑完就退的小脚本。
3.2 正则批量提取脚本特征,建立索引表
词频只能告诉你整体分布,想进一步知道“哪些脚本值得精读”,建议把特征提取出来做成索引表。特征包括:脚本里声明的包名、所有中文字符串中的关键词(比如“签到”“领取”“开始”“跳过”)、是否申请了截图权限、是否有悬浮窗控制逻辑。这些信息用正则就能抽。
import re import os import json script_dir = "./autojs_scripts" index = [] for root, _, files in os.walk(script_dir): for f in files: if not f.endswith(".js") and not f.endswith(".jsx"): continue path = os.path.join(root, f) text = open(path, encoding="utf-8", errors="ignore").read() text_lower = text.lower() index.append({ "file": path, "size": len(text), "has_capture": "requestScreenCapture" in text_lower, "has_floaty": "floaty" in text_lower, "has_loop": ("setInterval" in text_lower) or ("while(true)" in text_lower), "packages": re.findall(r'packageName\s*=\s*["\']([^"\']+)', text)[:3], "keywords": re.findall(r'text\("([^"]{2,8})"\)', text)[:10] }) with open("autojs_index.json", "w", encoding="utf-8") as fp: json.dump(index, fp, ensure_ascii=False, indent=2)这段 Python 代码的作用是把脚本目录里的每个.js文件扫描一遍,抽取出是否申请截图权限、是否有悬浮窗、是否有长驻循环、包名、关键词这五类信息,最后汇总成一个 JSON 索引。有了索引以后,想看“带悬浮窗的签到类脚本”,一行jq就能筛出来。errors="ignore"是为了防止个别脚本里混入了编码不完整的字符导致读取中断,这在 2021 年流传的脚本合集中很常见,因为很多脚本经历过聊天工具转发,文件头会出现编码残片。
3.3 用相似度去掉变种脚本,保住“有效样本数”
三千个听起来很多,但实际上去重以后可能只剩几百个甚至几十个。2019 年到 2021 年间,AutoJS 脚本圈流行“套壳”和“改说明文字”,同一套逻辑换了关键词就成了新脚本,这些属于变种样本。去重不需要用diff逐字节比对,只要按“去注释去空白后的函数名集合”来做相似度分组就够了。比较高效的做法是用 Python 的difflib.SequenceMatcher或者简单的 Jaccard 相似度。
import re from itertools import combinations from difflib import SequenceMatcher def normalize(text: str) -> str: text = re.sub(r"//.*", "", text) text = re.sub(r"/\*.*?\*/", "", text, flags=re.S) text = re.sub(r"\s+", "", text) return text def similarity(a: str, b: str) -> float: return SequenceMatcher(None, normalize(a), normalize(b)).ratio() # 用法示例(略去文件读取):pair_sim = lambda a, b: similarity(file_a, file_b)SequenceMatcher算的是字符级别的相似度,对于改过变量名、调过缩进、换过注释的变种脚本,相似度依然会落在 0.7 到 0.9 的区间,这样就很容易把重复样本找出来。这里给一个经验阈值:相似度大于 0.85 的,基本可以断定是同一个脚本的轻度修改,只需要保留其中一个精读即可。这样做的好处是,三千个实例经过“词频 + 索引 + 相似度”三层筛选后,可能只剩下三四十个真正值得逐行看的高质量样本,阅读成本急剧下降。
4. 实例脚本批量跑通前必须确认的三类参数与最高频的五个坑
4.1 悬浮窗、无障碍、截图三项权限的先后逻辑
AutoJS 脚本本质上是靠着“无障碍服务 + 悬浮窗 + 屏幕截图”这三个能力组合起来的,这三个能力的启用顺序决定了脚本能不能跑起来。正确顺序是:先开启无障碍服务,再申请悬浮窗权限,最后调用requestScreenCapture()。很多新人拿到脚本直接运行,弹出权限框就点允许,但实际上悬浮窗权限在部分国产 ROM 上默认是关的,脚本里如果用到了floaty模块创建悬浮按钮,就会在floaty.window()这一步直接报错。
常见做法是在脚本开头做一个权限自检:
auto.waitFor(); // 等待无障碍服务开启 if (!floaty.checkPermission()) { toast("请先开启悬浮窗权限"); app.startActivity({ action: "android.settings.action.MANAGE_OVERLAY_PERMISSION", data: "package:" + context.getPackageName() }); waitForPermission = true; } var captureReady = false; if (typeof requestScreenCapture !== "undefined") { captureReady = requestScreenCapture(false); }auto.waitFor()会阻塞直到无障碍服务真正处于开启状态,避免后续的findOne()调用直接抛异常。floaty.checkPermission()是 AutoJS 提供的悬浮窗权限检测接口,如果返回false,就用app.startActivity跳转到系统设置。requestScreenCapture(false)的第二个参数传false表示不需要保存到相册,避免每次截图都写入一张图片,降低存储压力。这里需要注意,部分模拟器对MANAGE_OVERLAY_PERMISSION的跳转 URL 支持不完整,需要手动去系统设置里开,脚本只能做一个兜底提示。
4.2 分辨率、模拟器、节点时延是参数重灾区
在 2021 年那个时间段,绝大多数“全自动脚本”都是模拟器用户在用,因为模拟器分辨率统一为 1280x720 或 1920x1080,坐标点击的派系特别流行。使用实体机的用户如果把模拟器脚本拿来直接跑,第一步就废了。所以跑脚本之前的第一个参数要确认的是device.width和device.height到底是多少。
第二个高频参数是模拟器的帧率设置。很多人在模拟器里把帧率设置成 60 帧,再把脚本里的sleep(500)改成sleep(200)来提速,结果控件还没渲染完就执行了点击,直接点到空白区域。这里我一般建议,凡是用到text(...).findOne()的脚本,findOne的超时时间不要低于 1500 毫秒,requestScreenCapture之后的第一张截图要留在sleep(1000)之后再处理,否则截到的是启动画面的白帧。
第三个参数是“点击后的等待时长”。很多脚本在click()之后马上进入下一次findOne,如果页面有出场动画或加载过程,就会造成节点未出现。这部分参数通常以脚本顶部的常量形式出现,搜索interval、delay、wait、sleepTime这些关键字就能找到。
4.3 2021 年实例脚本里最常见的五个坑
第一个坑是findOne()没加超时参数直接阻塞。AutoJS 的findOne()默认会一直等下去,如果页面没出现目标节点,整个脚本就卡死了。实例脚本里大量出现这种写法,必须手动改成findOne(2000)或findOnce(2000)这样的限时调用。
第二个坑是bounds()拼写成了bouds()。这个事在热词里都成了梗,因为bouds不是有效的 API,脚本运行到这一行直接报TypeError。造成这个现象的原因是早期部分教程里的拼写错误被大量复制,以讹传讹。如果拿到脚本发现报错信息指向bouds,直接用全局替换改成bounds即可。
第三个坑是click()目标超出了控件可点击区域。AutoJS 的click(x, y)是直接模拟点击,不管那个位置是不是控件的一部分。如果在desc("xxx").findOne()之后直接click(),在某些场景下因为是子元素而点击无效,必须改成click(desc("xxx").findOne().bounds().centerX(), ...centerY())才能在目标区域的中心生效。
第四个坑是截图权限申请后没有等待窗口创建。requestScreenCapture()返回后截屏服务还需要几帧的预热,立刻调用captureScreen()会返回null。加一个sleep(1000)或者用while (!captureScreen()) { sleep(100); }兜底。
第五个坑是"ui";开头的脚本和纯 JS 脚本混用。"ui";模式下的脚本使用ui.run线程模型,不能在主线程直接sleep()阻塞 UI 渲染,很多翻车现场就是在这里。判断方式很简单,看到ui.layout就按 UI 模式处理。
4.4 用两个最小脚本验证运行环境是否就绪
跑任何大型脚本之前,建议先跑下面两段最小验证脚本,确认环境没有暗病。
// 最小环境检查脚本:控件、悬浮窗、截图 auto.waitFor(); console.log("无障碍服务OK"); if (floaty.checkPermission()) { console.log("悬浮窗权限OK"); } if (typeof requestScreenCapture !== "undefined") { var image = requestScreenCapture(false); if (image) { console.log("截图权限OK"); } }// 控件树读取验证脚本 auto.waitFor(); var all = className("android.widget.TextView").findOnce(0); if (all) { console.log("控件读取正常,第一个TextView内容: " + all.text()); } else { console.log("当前页面没有TextView控件,检查是否在桌面或非应用界面"); }这两个脚本加起来不到半秒就能出结果。如果第一段提示截图权限失败,就检查系统设置里的悬浮窗/存储权限;如果第二段在应用页面上提示读不到控件,就说明无障碍服务没有真正挂载到当前应用上,重启无障碍服务通常会解决。这个步骤本质上是在替三千个实例做“运行前置检查”,省得一个个脚本报错后再回头排查环境问题。
5. 把高频实例技巧沉淀成可复用的几个片段,并解释它们的边界
看大量实例的终局不是把这些脚本原样保存起来,而是提炼出几个可以装进自己工具库的片段。这里选四个我认为 2021 年合集里最值钱,而且至今依然有效的技巧:找色代替找控件、翻页检测、多分辨率适配方法、用悬浮窗做启停控制。每一个都给出边界说明。
找色代替找控件适用于控件树里没有目标信息的场景,典型的例子是微信或抖音这类自绘 UI 的界面,控件树里只有View而没有text内容。做法是先截一张图,把目标点的颜色取出来,然后用images.findColor(image, color, region)定位。
function findColorAndClick(color, threshold) { threshold = threshold || 4; var img = captureScreen(); var p = images.findColor(img, color, { region: [0, 0, device.width, device.height], threshold: threshold }); if (p) { click(p.x, p.y); } img.recycle(); }images.findColor返回一个Point对象或null,threshold是容差值,0 表示精确匹配,数值越大容忍色差越大。这个函数适合元素位置不固定、背景却相对固定的场景,比如某个任务按钮在深色背景下是亮黄色。它的局限性在于无法处理滚动列表里同色块多个的问题,一屏里如果出现多个同色元素,findColor只会返回第一个匹配项。
翻页检测是那些挂机脚本能连续跑几个小时的关键。常见做法是检测“下一页”按钮是否还能找到,如果找不到就停止;更进一步,可以比对连续两帧截图的像素差异,如果差异太小,说明页面没有变化,大概率卡住了。像素差异检测直接用images.compare或者拿两张图逐像素遍历都可以,但逐像素遍历在低端机上性能偏慢,推荐对图片做缩放后再比对。
多分辨率适配的完整做法是,在脚本开头读取device.width和device.height,然后计算出与设计基准的缩放比例,所有坐标点和尺寸都乘以这个比例。请注意,这只能应对比例接近的设备,对平板这类宽高比变化大的设备不够用,更稳妥的是在平板设备上使用控件型选择器,完全不依赖坐标。
悬浮窗控制是长驻脚本的必备项。简单实现如下:
var w = floaty.window( <vertical> <button id="btn" text="停止" textSize="14sp"/> </vertical> ); w.setPosition(device.width - 200, 100); w.btn.click(() => { w.close(); threads.shutDownAll(); });这段代码里,floaty.window传入的是一个 XML 布局片段,setPosition把悬浮窗放到屏幕右上角,w.btn.click注册点击事件,点击后先关闭悬浮窗再调用threads.shutDownAll()停止所有后台线程。边界是threads.shutDownAll()会无差别终止当前引擎的所有线程,连定时任务一起结束,如果脚本里有需要善后清理的逻辑,要在它前面先保存状态。
最后说一句关于“史上最强”这类标题的看法。三千个实例脚本的价值从来不在数字本身,而在于它们是 AutoJS 生态在不同时期、不同设备、不同作者笔下的真实样本,里面既有完整优秀的工程实现,也有错误百出却能让你记住语法陷阱的残次品。把这些样本吃透,要比收集十个三千合集更能提升你的脚本生产力。
本文还有配套的精品资源,点击获取