1. 为什么需要自动化报名脚本
作为一个资深的大众点评VIP用户,我深知"霸王餐"活动的吸引力。每次打开APP看到琳琅满目的免费试吃活动,都忍不住想全部报名。但手动操作实在太费时费力了——要一个个点开活动页面,填写报名信息,再返回继续下一个。有时候因为操作太频繁,还会被系统误判为异常行为。
这就是我决定开发自动化脚本的初衷。通过AutoJS这个轻量级工具,我成功实现了:
- 自动识别可报名活动
- 智能填写报名信息
- 模拟真人操作轨迹
- 批量完成所有报名
实测下来,原本需要半小时的手动操作,现在3分钟就能搞定,而且成功率更高。最重要的是,终于不用再盯着手机重复点击了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 工具选型:为什么选择AutoJS
在开始开发前,我对比了几种常见的自动化方案:
| 工具名称 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Airtest | 图形化操作简单 | 需要连接电脑 | 游戏自动化 |
| Appium | 功能强大 | 配置复杂 | 专业测试 |
| AutoJS | 纯手机端运行 | 功能相对简单 | 日常自动化 |
最终选择AutoJS主要基于以下几点考虑:
- 纯手机端运行:不需要连接电脑,随时随地都能用
- JavaScript语法:学习成本低,社区资源丰富
- 轻量级:不占用太多系统资源
- 免root:大部分功能不需要root权限
特别适合像霸王餐报名这种简单的重复性操作。而且它的触摸模拟非常自然,不容易被系统检测到。
3. 开发前的准备工作
在动手写代码前,有几个关键步骤不能跳过:
3.1 分析操作流程
我花了些时间记录手动报名的完整流程:
- 打开大众点评APP
- 进入"免费试"频道
- 切换到"VIP专享活动"
- 浏览活动列表
- 点击"免费抽"按钮
- 填写报名信息
- 提交并返回
每个步骤都要记录下界面元素的变化和操作方式。这个分析过程很重要,能帮助我们发现潜在的坑点。
3.2 获取界面元素信息
AutoJS主要通过控件的属性来定位元素。我们需要获取:
- 控件ID(如id('main_listview'))
- 文本内容(如text('VIP专享活动'))
- 类名(如className('android.widget.ImageButton'))
可以使用AutoJS自带的"布局分析"功能查看这些信息。建议多截图保存,方便后续调试。
3.3 处理特殊交互
有些操作需要特别注意:
- 长按破解:某些按钮需要长按才能触发
- 自然滚动:简单的scroll()可能无效,需要模拟手势滑动
- 等待机制:网络加载需要合理设置等待时间
这些细节处理不好,脚本很容易失效。后面会具体讲解如何实现。
4. 核心代码实现详解
现在进入最关键的代码部分。我会拆解每个功能模块,解释实现思路和注意事项。
4.1 启动APP并进入目标页面
javascript复制auto.waitFor();
const appname = '大众点评';
app.launchApp(appname);
console.log(device.width,device.height);
// 进入免费试频道
id('main_listview').waitFor();
let list = id('main_listview').findOne();
list.children()[1].children()[3].findOne(className('android.widget.ImageButton')).click();
这段代码有几个关键点:
auto.waitFor()确保无障碍服务已开启app.launchApp()启动指定APP- 打印设备分辨率方便调试坐标
- 通过控件层级定位"免费试"入口
注意不同手机型号的控件结构可能不同,需要适当调整children()的索引值。
4.2 处理VIP专享活动入口
javascript复制console.log('进入vip专享活动频道');
while (text('VIP专享活动').findOne().parent().findByText("全部").size() == 0);
let allBtn = text('VIP专享活动').findOne().parent().findByText("全部").get(0).parent();
let allBtnBounds = allBtn.bounds();
press(allBtnBounds.left, allBtnBounds.top, 100);
这里有个重要技巧:
- 使用
press()而不是click(),因为某些按钮有长按校验 - 100ms的按压时间既不会太短被忽略,也不会太长显得异常
- 先确保目标元素加载完成再操作
4.3 识别并点击报名按钮
javascript复制console.log('开始搜索可点击的免费抽按钮');
let btn = text("免费抽").findOne(3000);
if(btn){
let bounds = btn.bounds();
press(bounds.left, bounds.top, 1);
let isOk = text('免费试活动详情').findOne(3000);
if(isOk){
console.log('点击免费抽按钮成功');
let bmBtn = text("我要报名").findOne(4000);
if(bmBtn){
bmBtn.click();
}else{
let wybmBtn = text("已报名,看看其他活动").findOne();
if(wybmBtn){
console.log('已报名,返回免费试首页');
wybmBtn.click();
}
}
}else{
console.log('点击免费抽按钮失败');
}
}else{
console.log('没有找到免费抽按钮');
}
这段代码实现了:
- 查找"免费抽"按钮
- 模拟点击进入详情页
- 检查是否已报名
- 处理各种异常情况
建议添加足够的等待时间和日志输出,方便排查问题。
4.4 填写报名信息并提交
javascript复制text('确认报名').waitFor();
// 判断是否有分店
if(text("请选择分店").exists()){
click("请选择分店",0);
className('android.widget.ListView').waitFor();
className('android.widget.ListView').findOne().child(1).click();
}
// 判断是否有套餐
if(text("请选择套餐").exists()){
click("请选择套餐",0);
className('android.widget.ListView').waitFor();
className('android.widget.ListView').findOne().child(1).click();
}
while(!click("确认报名",0));
text('报名成功').waitFor();
while(!click("回到首页",0));
这部分处理了两种常见情况:
- 需要选择分店
- 需要选择套餐
默认都选择第二个选项(通常是最热门的)。如果业务需要,可以扩展更智能的选择逻辑。
5. 高级技巧与优化建议
经过一段时间的实际使用,我总结出几个提升脚本稳定性的技巧:
5.1 模拟自然滑动
简单的scroll()方法容易被检测到,建议改用gesture()模拟真人滑动:
javascript复制function naturalSroll(startY, endY){
let steps = 50;
let interval = 5;
let points = [];
for(let i=0;i<steps;i++){
points.push([device.width/2, startY+(endY-startY)*i/steps]);
}
gesture(interval, points);
}
这个函数模拟了带加速度的滑动轨迹,实测效果更自然。
5.2 随机化操作间隔
在关键操作间添加随机延迟,避免固定节奏:
javascript复制function randomDelay(){
sleep(random(300, 1500));
}
5.3 异常处理与重试
网络不稳定时,需要完善的错误处理:
javascript复制function safeClick(selector, maxRetry=3){
for(let i=0;i<maxRetry;i++){
try{
if(click(selector)) return true;
}catch(e){
console.warn(e);
}
sleep(1000);
}
return false;
}
5.4 多账号支持
如果需要管理多个账号,可以这样扩展:
javascript复制let accounts = [
{name:"账号1", username:"xxx", password:"xxx"},
{name:"账号2", username:"xxx", password:"xxx"}
];
accounts.forEach(account=>{
console.log("处理账号:"+account.name);
// 登录逻辑
// 报名逻辑
});
6. 实际效果与注意事项
经过3个月的持续使用和优化,这个脚本已经非常稳定:
- 平均报名成功率:98%
- 单次运行时间:3-5分钟
- 最多一次性报名:20+个活动
但使用时需要注意:
- 不要设置太短的执行间隔,建议至少间隔1小时
- 定期检查脚本是否还能正常工作,APP更新可能导致失效
- 合理控制报名数量,避免被系统限制
- 最好在WiFi环境下运行,减少网络问题
如果遇到脚本失效的情况,通常只需要调整元素定位部分就能修复。建议保存历史版本,方便快速回滚。
