auto.waitFor();
var appName = "起点读书";
var pkgName = "com.qidian.QDReader";
launchApp(appName);
sleep(6000);
enterWelfare();
// 处理小游戏任务(最多3个)
for (var i = 0; i < 3; i++) {
var gameBtn = text("去微信立即开玩").findOne(3000);
if (!gameBtn) break;
gameBtn.click();
toast("进入微信小游戏,挂机30秒");
sleep(32000);
// 点击右上角圆圈返回微信
clickCircleButton();
sleep(2000);
// 直接重新打开起点
launchApp(appName);
sleep(6000);
// 重新进入福利中心
enterWelfare();
sleep(2000);
}
// 视频任务
doVideoTasks();
toast("全部完成");
// ==================== 函数 ====================
function enterWelfare() {
var meTab = text("我").findOne(2000);
if (meTab) meTab.click();
sleep(2000);
var welfare = textMatches(/(.*福利.*|.*活动中心.*)/).findOne(3000);
if (welfare) {
welfare.click();
sleep(3000);
}
}
function clickCircleButton() {
// 右上角圆圈坐标
var x = device.width - 80;
var y = 120;
click(x, y);
sleep(500);
click(x - 30, y); // 备用偏移点击
}
function doVideoTasks() {
for (var i = 0; i < 5; i++) {
var watchBtn = textMatches(/(.看视频.|.去观看.)/).findOne(3000);
if (!watchBtn) break;
watchBtn.click();
sleep(random(32000, 38000));
var closeBtn = desc("关闭").findOne(2000)
|| text("关闭").findOne(2000);
if (closeBtn) closeBtn.click();
sleep(random(3000, 5000));
if (random(1, 10) > 8) break;
}
}找找问题
回答
该脚本整体逻辑清晰,但在实际运行中存在几个影响稳定性、设备兼容性和任务完成率的關鍵问题。以下是具体分析与优化方案:
1. 硬编码坐标点击导致设备不兼容
clickCircleButton() 使用 device.width - 80 和固定 y=120 进行点击。不同手机分辨率、状态栏高度、微信小游戏UI布局差异会导致点击失效或误触其他控件。
优化方案:优先使用UI控件选择器,若无法获取则使用系统返回键。
// 文档地址 https://docs.hamibot.com/
function clickCircleButton() {
var closeBtn = desc("关闭").findOne(2000) || text("关闭").findOne(2000);
if (closeBtn) {
closeBtn.click();
} else {
back(); // 返回键兼容性远高于坐标点击
}
}
2. 循环内重复冷启动应用逻辑脆弱
每次小游戏结束后调用 launchApp(appName) 会强制重新打开应用,可能导致应用冷启动耗时增加、页面状态丢失或触发风控验证。且 enterWelfare() 假设应用一定在首页,实际返回后可能停留在其他页面。
优化方案:使用 back() 返回起点读书,等待包名切换回目标应用后,再动态寻找福利入口。
// 替换原循环内的重启逻辑
back();
sleep(1000);
// 等待应用恢复前台
while (currentPackage() !== pkgName) {
sleep(500);
}
// 重新进入福利中心前,先确保在“我”页面
text("我").waitFor();
enterWelfare();
3. 固定休眠时间过长且缺乏动态等待
sleep(6000)、sleep(32000) 等固定等待在网络波动或设备性能差异时极易导致脚本卡死或提前执行下一步。
优化方案:使用 waitFor() 或循环检测关键控件出现后再执行下一步,大幅缩短无效等待时间。
// 示例:替换固定 sleep
text("我").waitFor(); // 阻塞等待直到控件出现
4. 视频任务随机提前退出
if (random(1, 10) > 8) break; 会导致约20%的概率未完成所有视频任务就中断,违背自动化任务目标。
优化方案:移除随机中断逻辑,改为检测不到目标按钮时自然退出循环。
5. 缺少空值保护与异常处理
部分 .click() 调用前未严格校验对象是否为 null,在UI未加载完成或控件被遮挡时可能抛出 TypeError 导致脚本崩溃。
优化方案:所有UI操作前增加显式判断。
优化后的完整核心逻辑(兼容 Rhino 1.7.15)
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
var appName = "起点读书";
var pkgName = "com.qidian.QDReader";
launchApp(appName);
text("我").waitFor(); // 动态等待首页加载
sleep(1000);
enterWelfare();
// 处理小游戏任务(最多3个)
for (var i = 0; i < 3; i++) {
var gameBtn = text("去微信立即开玩").findOne(3000);
if (!gameBtn) break;
gameBtn.click();
toast("进入微信小游戏,挂机30秒");
sleep(32000);
clickCircleButton();
sleep(1500);
// 返回并等待应用恢复
back();
sleep(1000);
while (currentPackage() !== pkgName) {
sleep(500);
}
text("我").waitFor();
enterWelfare();
sleep(1000);
}
doVideoTasks();
toast("全部完成");
function enterWelfare() {
var meTab = text("我").findOne(2000);
if (meTab) meTab.click();
sleep(1000);
var welfare = textMatches(/(.*福利.*|.*活动中心.*)/).findOne(3000);
if (welfare) {
welfare.click();
sleep(2000);
}
}
function clickCircleButton() {
var closeBtn = desc("关闭").findOne(2000) || text("关闭").findOne(2000);
if (closeBtn) {
closeBtn.click();
} else {
back();
}
}
function doVideoTasks() {
for (var i = 0; i < 5; i++) {
var watchBtn = textMatches(/(.*看视频.*|.*去观看.*)/).findOne(3000);
if (!watchBtn) break;
watchBtn.click();
// 动态等待关闭按钮出现,替代固定休眠
var closeBtn = desc("关闭").findOne(35000) || text("关闭").findOne(35000);
if (closeBtn) {
closeBtn.click();
} else {
back(); // 超时则返回
}
sleep(2000);
}
}
最佳实践建议
- 优先使用控件选择器:
text()、desc()、id()的稳定性远高于click(x, y)。坐标点击仅作为最后兜底方案。 - 动态等待替代固定休眠:使用
waitFor()或findOne(timeout)可显著提升脚本在不同设备上的执行效率。 - 包名切换检测:跨应用跳转时,使用
currentPackage()循环检测可避免脚本在后台应用未恢复时误操作。 - Rhino 兼容性:脚本已严格使用
var声明、传统function语法,避免箭头函数与默认参数,确保在 Hamibot 底层引擎稳定运行。
按上述调整后,脚本的跨设备兼容性、任务完成率及运行稳定性将得到显著提升。如有特定机型适配问题,可提供具体报错日志进一步排查。