Autojs实战:从零实现番茄小说自动翻页并打包Apk全流程
2026/9/15 13:05:30 网站建设 项目流程

如果你一直在找一种方式,让手机里的阅读App自动翻页、自动签到、自动整理书架,Autojs这个安卓自动化工具几乎就是为此准备的。我最近把一个真实项目从零到一完整做了一遍:用Autojs脚本控制番茄免费小说,实现自动翻页阅读,最后把脚本打包成独立Apk,并把源码按模块重新整理好。整个过程踩了不少坑,特别是Apk打包和真机坐标适配这一块,今天拆开来讲清楚。适合正在学Autojs、想做一个能落地的自动化项目、或者想了解脚本如何变成安卓应用的人参考。

1. 项目到底在做什么:Autojs + 番茄小说 + Apk/源码的完整拼图

1.1 一句话讲清需求

这个项目不是简单的“写一段脚本点两下就完事”,而是把一条完整的自动化链条走通:先写Autojs脚本,让番茄免费小说在指定时间自动打开、进入书架、打开某本小说、自动翻页阅读;再把脚本的源码工程化组织起来,封装成可维护的模块;最后把它打包成一个独立的Apk,装在另一台没有安装Autojs的安卓手机上也能运行。

标题里出现“Apk文件和源码”,其实对应两个非常实际的需求。第一,脚本写好了不方便发给别人,给朋友装一个Autojs再导入脚本,门槛太高,直接打包成Apk双击安装更符合普通用户习惯。第二,脚本一旦超过两三屏代码,就容易变成一团乱麻,源码的模块化、版本管理和路径配置必须从一开始就规划好,否则后面加一个“定时阅读”功能都要翻半天代码。

所以你可以把这个项目理解成:用Autojs做应用层自动化,用Android应用的打包思路做交付,用软件的工程化思维做源码管理。三者合在一起,才是一个“实战教程”该有的完整度。

1.2 为什么选择Autojs而不是其他自动化方案

安卓自动化工具并不少,Appium、Udacity、Tasker、无障碍脚本、ADB命令都能做类似的事情,但Autojs在这个场景下几乎是首选。原因有三。

第一,Autojs基于JavaScript,写起来没有Java或Kotlin那么重,不需要Android Studio,不需要Gradle构建,在手机上装一个App就能开始调试。对于“我想让App自动翻页”这种需求,打开Autojs写几行代码,点运行,几秒钟就能看到效果,这种即时反馈对学习自动化非常有帮助。

第二,Autojs自带控件分析能力,可以通过文本、ID、描述、按钮文字等属性直接找到界面上的元素。比单纯用坐标点击要稳定得多。比如番茄小说的“书架”按钮,在不同手机上可能坐标不一样,但文字“书架”基本不会变,我们直接找text("书架")再点击,就能跨机型适配。

第三,Autojs可以打包成Apk。这是很多脚本框架做不到的,或者做起来非常繁琐。Autojs把JavaScript引擎、自动化服务、打包工具都集成在一起,配置好图标和包名就能生成独立应用,非常适合用来做个人工具类App。

当然它也有局限性。比如无障碍服务在某些定制ROM上会被系统杀掉,或者需要用户手动开启权限;再比如对iOS完全无能为力。但这些都不影响它在“安卓手机自动化”这个场景里的实用地位。

1.3 这个方案解决了什么痛点

真正喜欢在手机上看小说的人,应该都有这种体验:一章读完,手要抬起来点一下屏幕,冬天缩在被子里尤其难受;有时候看久了手指头酸,眼睛也累。更别说一些需要“挂机阅读时长”的场景,手动翻页非常消耗耐心。

这个项目能解决的第一个痛点,就是把“手动翻页”变成“脚本翻页”,让手机按照设定好的时间间隔自动翻页,而且可以设定总时长,到点自动停止。第二个痛点是效率,写一次脚本,以后所有番茄小说上的书籍都能复用,只需要改一下书目匹配规则。第三个痛点是工程化能力,很多人写自动化脚本都是写完就丢,三个月后想复用发现连自己都看不懂,但按照源码管理的方式组织好之后,每次打开都知道该改哪个文件。

2. 动手前的环境准备:工具链与测试机选择

2.1 完整工具清单

做这个项目之前,我先列一个基础工具清单,这些不是可有可无的,而是每一件都会在后面的步骤里被用到。

工具/资源用途备注
安卓手机一台跑Autojs和番茄小说建议Android 7以上,真机优先
Autojs编写和运行脚本我用的是Autojs Pro 4.1.1,4.x开源版也可
番茄免费小说App自动化操作目标建议固定版本,关闭自动更新
USB数据线连接电脑做日志调试部分手机需要开启USB调试
VSCode或任意文本编辑器管理源码文件配合Autojs插件更好
Git做源码版本管理本地仓库或远程仓库都可以
打包工具生成ApkAutojs Pro内置打包,或用官方离线打包

如果你手头只有一台手机,没有电脑,也能完成大部分工作,因为Autojs自带编辑器,可以直接在手机上写代码。但有电脑会舒服很多,至少日志查看和源码管理不会那么痛苦。最推荐的组合是一台主力机做开发,一台旧手机专门跑自动化测试,因为自动化过程中要反复开权限、杀后台、装包,在主力机上很容易影响正常使用。

2.2 Autojs版本怎么选

Autojs的版本情况比较乱,市面上的选择大致有三类:GitHub上的开源4.x版本、商业化的Autojs Pro版本、以及各种个人修改版。开源4.x版免费,满足控件操作、JavaScript语法等基本需求,但打包功能比较弱,很多功能需要自己配。Autojs Pro打包能力更成熟,支持图标配置、包名配置、离线打包,还支持把脚本加密到Apk里,适合做分发。

我的建议是,如果你刚开始学,用开源4.x版就够了;如果后续要正式打包成Apk发给别人,再考虑Pro版。这里的核心原则是:别从不明渠道下载来路不明的修改版,因为你写的脚本会申请无障碍权限和悬浮窗权限,这已经是系统敏感权限,如果运行在一个被植入后门的“Autojs”里,风险非常大。尽量去官方渠道或者GitHub下载。

2.3 测试机与番茄小说App的准备

自动化最怕的就是环境变化,而番茄小说是一个经常更新的App,界面结构会变,控件ID也会变。我的做法是装好一个稳定版本之后,先去应用商店里把“自动更新”关掉。如果你对某个版本的界面特别熟悉,可以保留那个版本的安装包作为测试基准。

测试机建议用真机,不要用模拟器。原因很简单,模拟器里的屏幕分辨率和真实手机不同,番茄小说对模拟器的兼容性也不稳定,容易出现控件信息读取不到的情况。真机上有一类比较容易踩坑的ROM,比如部分国产定制系统会默认禁止后台自启动,Autojs的无障碍服务跑一会儿就被系统回收,导致脚本突然失去响应。碰到这种情况,需要去系统设置里把Autojs和番茄小说都设为“允许后台运行”,最好还能锁定最近任务。

准备工作的最后一步,是安装设置好Autojs后,先手动打开一次系统“无障碍”开关,然后在Autojs里跑一个最简单的脚本,比如toast("hello"),确认脚本能正常弹窗。这个基础环境通了,再继续往下写自动化逻辑。

3. 核心脚本设计:从打开App到自动翻页

3.1 先想清楚整体状态机

很多人写Autojs脚本是一股脑从上往下写,先打开App,然后sleep,点一个按钮,再sleep……这里一个sleep那里一个sleep,脚本跑起来就像猜谜一样。我会建议你先画出整个流程的状态机,不需要很复杂,但在脑子里要清楚当前处于什么状态。

这个项目的流程大致是:启动脚本 -> 开启无障碍 -> 进入番茄小说 -> 判断是否在书架页 -> 打开目标书籍 -> 进入阅读页 -> 等待正文加载 -> 执行翻页 -> 翻到指定页或运行到指定时长 -> 退出阅读页 -> 回到桌面。

每次操作之后,脚本都要问自己一个问题:我现在是不是真的到达了预期状态?而不是盲目sleep。比如我执行click(button)之后,不能马上接着翻页,而应该先判断阅读页有没有出现,如果没出现就等待,等超过5秒还没出现,就说明点击失败了,需要回到上级流程。

3.2 用控件查找而不是死坐标:为什么我强烈推荐

我最早学Autojs时,也喜欢用click(x, y),因为简单,看到屏幕哪里能点就点哪里。但后来发现不同手机的屏幕尺寸不一样,同一个按钮坐标可能差出几十甚至上百像素,到朋友手机上脚本就失灵了。

Autojs比较优雅的做法是控件查找。它能把界面上的按钮、文本框、列表项解析成对象,我们可以通过text()id()className()等条件去匹配。比如番茄小说书架页一般会有“书架”这个文本,我们可以这样写:

auto.waitFor() launchApp("番茄免费小说") sleep(2000) var shelfTab = text("书架").findOne(3000) if (shelfTab) { shelfTab.click() toast("已进入书架") } else { toast("没有找到书架tab") }

注意findOne(timeout)方法是阻塞等待,最多等3秒,如果找到元素就返回,找不到返回null。这种写法的好处是,即使小说App启动慢,或者页面加载有延迟,脚本也能等一等再判断,而不是盲目sleep。

3.3 翻页逻辑的两种实现方式

番茄小说阅读页的翻页方式,在App设置里通常有“仿真”、“滑动”、“覆盖”等几种模式。对自动化脚本来说,最稳妥的翻页方式是模拟点击阅读区的右侧或执行一次左滑手势,具体要看App当前的翻页模式。

如果你使用的是“仿真”或“覆盖”模式,通常点一下屏幕右侧就到下一页,脚本可以这样实现:

function nextPageByClick() { let w = device.width let h = device.height click(w * 0.85, h * 0.5) }

如果你使用的是“滑动”模式,那就需要模拟手指向左滑:

function nextPageBySwipe() { let w = device.width let h = device.height swipe(w * 0.8, h * 0.5, w * 0.2, h * 0.5, 300) }

你可能会问,到底应该用哪种?我建议先花两分钟手动打开一本书,看正文区域点一下会不会翻页。如果会,就用点击法;如果点一下只是弹出菜单,那就用滑动法。实际项目中最好的做法是两种都写,用一个配置项控制,这样在不同的翻页模式下都能跑。源码里可以定义一个readerConfig对象,里面放上翻页方式翻页间隔总阅读时长等参数。

3.4 定时与防沉迷设计

自动翻页虽然是方便,但如果不加限制,很容易让手机一直亮屏跑一整天,一是费电,二是不健康。我在脚本里加了一个“运行时长”和“翻页间隔”参数:

var config = { interval: 8000, // 每8秒翻一次页 maxDuration: 30 * 60 * 1000, // 最多运行30分钟 targetBook: "斗破苍穹" // 示例书名,按实际替换 }; var startTime = Date.now(); while (Date.now() - startTime < config.maxDuration) { if (text("目录").exists() || text("设置").exists()) { // 可能弹出菜单栏,点一下正文关闭 click(device.width / 2, device.height / 2); } nextPageByClick(); sleep(config.interval); }

这个设计可以用一个while循环控制,到时间就退出,然后回到桌面。在真实项目中,我还会把到期时间通知出来,比如用Autojs的notify发送一个本地通知,提醒用户“今天的自动阅读已完成”。

这里也顺便提醒一句:自动化脚本的目的是辅助自己,不是替代人去滥用某个App,所以使用时要遵守番茄小说的用户协议,不要用脚本去刷奖励、刷时长、恶意下载内容。我做的只是正常的“模拟翻页阅读”,这是技术演示和学习范畴。

3.5 异常弹窗和加载失败怎么处理

自动阅读过程中,最大的敌人不是代码本身,而是界面上的各种不确定性。比如启动App后偶尔弹“青少年模式”,阅读过程中弹“继续阅读”的引导,断网时显示加载失败,这些都会让脚本卡住。

我的处理思路是:在一个翻页循环里,每次翻页前先做一个“弹窗清理”动作。用Autojs的文本选择器去查找那些常见的关闭按钮,比如“知道了”、“关闭”、“取消”、“暂不”等,找到了就点掉。代码可以封装成一个函数:

function dismissDialogs() { var closeTexts = ["知道了", "关闭", "取消", "暂不", "以后再说", "立即关闭"]; for (var i = 0; i < closeTexts.length; i++) { var btn = text(closeTexts[i]).findOne(200); if (btn) { btn.click(); sleep(500); } } }

注意findOne(200)是只等200毫秒,找不到就立刻返回null,避免每个弹窗文本都等很久。这个方法不能保证100%处理所有弹窗,但能覆盖大多数常规提示。如果遇到一个完全没见过的弹窗,脚本会在下一次翻页时因为找不到目标控件而退出,所以我在主循环里还会加一个“连续失败次数”统计,连续失败超过3次就停止并截图,方便之后排查。

3.6 源码模块化:别再把所有代码堆在一个文件里

当脚本功能越来越多时,单文件模式就很难维护了。我最终把源码整理成这样的结构:

auto-read-novel/ ├── project.json ├── main.js ├── config.js ├── modules/ │ ├── app.js │ ├── reader.js │ ├── dialog.js │ └── logger.js └── res/ └── icon.png

main.js只负责启动入口,调用app模块打开应用,再调用reader模块开始阅读。config.js放所有可变参数。modules/app.js封装启动App、返回桌面、判断当前应用等操作。modules/reader.js负责阅读页的定位、翻页、章节检测。modules/dialog.js专门处理各种弹窗。modules/logger.js负责输出日志到文件。

这样拆开之后,项目的好处就体现出来了。我想改翻页间隔,只需要打开config.js;想增加新的弹窗文案,只需要改dialog.js;想换一个阅读App,只需要重写reader.js,其他模块基本可以复用。这就是源码工程化的意义。

4. 从源码到Apk:把脚本变成独立安卓应用的完整路径

4.1 为什么要打包成Apk

既然脚本在Autojs里能直接跑,为什么还要打包成Apk?我总结下来有三个原因。

第一,方便分发。你写了一个自动化脚本,想给家里人用,但他们手机上不一定装了Autojs,就算装了也不会导入脚本、不会开权限。打包成Apk之后,他们只需要像安装普通App一样安装,然后按提示开启无障碍服务就行。第二,保护源码。Autojs的脚本文件本质上是JavaScript文本,发给别人就等于公开源码。打包成Apk时可以对脚本做加密或混淆,降低被直接复制阅读的门槛。第三,运行更稳定。打包后的Apk不再需要Autojs主程序,减少一个被系统回收的环节。

4.2 Autojs打包Apk的具体步骤

我以Autojs Pro为例,演示一个稳定的打包流程。首先在Autojs Pro中新建一个项目,把前面整理好的源码目录结构放进去。然后检查project.json,这是打包配置的关键文件,比想象中的还要重要。

{ "name": "番茄小说自动阅读助手", "version": "1.0.0", "packageName": "com.example.autoread", "mainScriptFile": "main.js", "icon": "res/icon.png", "build": { "targetSdk": 30, "minSdk": 21, "sign": { "keystore": "my.keystore", "alias": "myalias", "password": "123456" } } }

配置好之后,如果用Autojs Pro的图形界面,直接点击“打包”按钮,它会自动完成JavaScript打包、资源合并、签名生成Apk。整个过程大概几分钟。如果要用命令行,Autojs也提供了打包脚本,可以在电脑上用Node.js调用,方便集成到CI流程里,但新手阶段用图形界面就够了。

4.3 打包时的权限配置和注意事项

Autojs打包出来的Apk,和普通App一样也会申请一系列权限。最少需要以下这几个:

  • 无障碍服务:这是Autojs能模拟点击、读取控件的前提
  • 悬浮窗权限:有些自动化操作需要显示悬浮窗,或者做日志弹窗
  • 前台服务权限:避免脚本在后台运行时被系统杀掉
  • 存储权限:保存日志、截图等

在这些权限里,最容易出问题的是“无障碍服务”。很多定制ROM在应用安装后会默认禁止无障碍服务,需要用户手动去系统设置里开启。所以打包后的Apk,应该在首次启动时做一个引导页,告诉用户怎么找到这个开关。我自己的做法是:在main.js启动时先执行auto.waitFor(),如果无障碍没有开启,就用alert提示用户去设置,直到用户开启才进入主逻辑。

另外签名文件要保管好,因为在后续升级版本时,必须用同一个签名文件签名,否则系统会报“已安装应用签名不一致”而无法覆盖安装。很多人在打包第一次后把keystore文件丢了,等到版本升级时只好卸载重装,用户数据也就全没了。

4.4 安装Apk时常见的几个坑

第一次把打包好的Apk传到手机上安装,大概率会遇到问题。我这里列几个最常见的:

现象原因解决办法
安装时提示“解析软件包时出现问题”Apk文件损坏,或者系统版本过低重新打包,检查minSdk是否低于手机系统版本
提示“安装失败,更新包与现有应用签名不一致”之前安装了同一个包名的其他签名应用卸载旧应用后安装,或者严格统一签名
安装后打开就闪退脚本代码里用了系统不支持的API,或没有开启无障碍时直接调用点击在启动入口加异常捕获,增加权限判断
图标显示为默认机器人res/icon.png路径写错检查project.json中icon路径,图片必须是PNG格式

我踩得最狠的一次,是把targetSdk设得太高,结果在Android 7的旧手机上打开直接崩溃,后来改成targetSdk 30就稳定了。建议打包时尽量考虑你目标用户手机的Android版本,不要追求最新SDK。

5. 常见问题与排查技巧实录

5.1 脚本跑一会就卡死在阅读页

这是自动化脚本最常见的问题,主要原因是某个元素没有出现,脚本却在等待它,或者不停点击同一个位置导致进入了一个无法预期的页面。排查时我会先把logger打开,在关键节点都输出日志,比如“进入阅读页”、“翻页完成”、“发现弹窗”,这样能定位到卡在哪一步。

另一个容易忽略的原因是屏幕常亮。如果手机在脚本运行过程中锁屏了,控件查找会全部失效。解决方法是脚本开始时执行device.keepScreenOn(),或者用Autojs的device.wakeUp()在休眠后唤醒屏幕。在打包成Apk时,最好申请“唤醒锁”权限,否则无法保持屏幕常亮。

5.2 翻页坐标在部分机型上失效

不同手机的屏幕长宽比不一样,单纯用百分比坐标虽然能适配大部分情况,但有些全面屏手机因为系统手势区占据了底部,点击坐标会偏到导航栏上。我的经验是:翻页点击点不要放在最底部,尽量放在屏幕纵向中央区域,比如y = h * 0.5,同时避免点击到左右边缘。

还有一个小技巧:用device.widthdevice.height获取到的尺寸是屏幕物理像素,如果番茄小说开启了“深色模式”或“夜间模式”,正文背景和控件位置不会变,但弹窗文字颜色可能变化,这会影响文本选择器匹配吗?正常情况下不影响,因为text()匹配的是控件文字内容,不依赖颜色。但如果某个弹窗文字是图片形式,那就无法用文本选择器定位,只能借助OCR或者固定坐标,这种情况就只能靠截图人眼判断了。

5.3 Apk打包后无法打开番茄小说App

我遇到过一种情况:打包后的Apk已经申请了存储权限和悬浮窗权限,但在启动番茄小说时提示“未安装”。后来发现是打包Apk时包名冲突,导致系统把两个应用搞混了。解决方法是把packageName设置成一个自定义的、不和其他应用冲突的包名,比如com.yourname.autoreader

还有一种情况是Android 10以后对后台启动Activity做了限制,如果Autojs脚本是在后台通过定时任务触发,直接调launchApp("番茄免费小说")可能被系统拦截。这个时候需要把定时触发改成前台通知,或者使用app.startActivity显式指定包名和Activity,但这需要确保你能拿到正确的组件信息,而且不涉及绕过系统安全限制。

5.4 番茄小说更新后脚本失效

App更新是自动化项目最大的威胁之一。今天还能找到的“书架”按钮,下次更新后可能从text("书架")变成了content-desc("书架"),甚至完全换了一个控件。我的应对办法是:在config.js里维护一组备选选择器,匹配不到第一批就用第二批。

var shelfSelectors = [ function() { return text("书架").findOne(1000) }, function() { return desc("书架").findOne(1000) }, function() { return id("tab_shelf").findOne(1000) } ];

从产品角度说,这也是为什么要把源码管理好。因为一旦App更新,你需要在半小时内更新脚本并重新打包Apk,如果代码是一团乱麻,根本做不到快速响应。用Git管理源码,每次App更新之后还能对比之前的改动,快速定位需要修改的地方。

5.5 源码工程备份与Git管理

源码是项目最大的财富,所以我从一开始就用Git。项目根目录下添加了一个.gitignore

node_modules/ build/ dist/ *.keystore *.jks local.properties

签名文件、构建产物都不应该进版本库,否则容易泄露密码。每次完成一个稳定版本,就打一个tag,例如v1.0.0。这样以后哪个版本出了问题,可以快速切回去对比。

6. 项目复盘与下一步扩展

6.1 我从这个项目里学到的三点经验

第一,自动化脚本的核心不是写代码,而是“处理和预期不符的界面状态”。你永远不知道用户会在什么情况下打开你的App,也永远不知道App自己的弹窗规则是什么,所以脚本必须设计成“每走一步都要确认状态”。

第二,控件优先,坐标兜底。能用textdescid定位元素就尽量用,实在不行再用坐标。坐标只是一种快速方案,不是稳定方案。

第三,Apk打包不是一个简单的按钮。它涉及包名、签名、targetSdk、权限配置、手机系统兼容性,任何一个环节没处理好,用户拿到手就是一串“安装失败”。所以一定要在自己的真机上做完整测试,再分发给别人。

6.2 后续还能怎么扩展

这个项目的扩展空间其实很大。你可以给脚本加定时阅读功能,比如每天晚上十点自动打开小说阅读半小时;也可以把每天的阅读页数记录到本地SQLite里,周末生成一个阅读统计;还可以用Autojs的邮件或Webhook能力,把阅读完成通知推送到自己的服务器。

我甚至建议你试试把同一个自动阅读脚本适配到其他阅读App上,比如起点、微信读书、掌阅。虽然不同App的控件结构差异很大,但你已经有了一套模块化源码,只需要替换reader.js里的选择器部分,其他逻辑基本能复用。这个过程会是很好的学习素材,也会让你对安卓自动化有更深入的理解。

对我来说,这个项目最大的价值不是让番茄小说“自己看书”,而是把一套完整的自动化项目从脚本写到了Apk分发。它让我理解了安卓自动化真正的难点:不是写代码,而是适配每个不可控的界面状态。如果你也想练手,我建议先别急着写大而全的功能,做一个5分钟内能跑起来的翻页脚本,然后在这个基础上一点一点加状态判断。等你的脚本能在不同手机上稳定运行三天,你对Autojs的掌握就已经超过大多数人了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询