YYPOST群发软件 发表于 2026-9-9 06:36:06

通用找图OCR点字完整脚本骨架


通用找图OCR点字完整脚本骨架










// ============================================================================
//AIWROK 通用「找图 + OCR 点字」完整脚本骨架(案例 #02 配套)
// ============================================================================
//这才是一条正常在跑的脚本:复位 → 主循环 → 每轮 找图/OCR → 命中就点 → 下滑 → 随机等待 → 打日志。
//会持续运行(默认 20 轮、每轮等 1.5~4 秒,几十秒~几分钟),不是一秒结束的自检。
//
//用法:
//    1) 只改【配置区 CFG】:targets 里填你的按钮模板(base64,没有就留 null),words 里填界面真实文字;
//    2) 直接运行,看日志:每一轮做什么、点没点、坐标多少、下一轮什么时候开,全打出来;
//    3) 里面 findPic / ocrFind / doClick / doSwipe 都是可抠走的通用函数,避坑写法已焊死:
//       判 null 不崩、百分比坐标 percentToWidth/Height 转像素、截图用完 recycle。
//
//安全:默认 RUN_CLICK=false 时只“找到并打印坐标”不真点,先空跑验证再放开,防误点。
// ============================================================================

// ============================ 一、配置区(只改这里) ============================
var CFG = {
    rounds: 20,                     // 跑多少轮后自动结束(想一直跑就写很大,如 999999)
    runClick: true,                // ★先 false 空跑看日志,确认找得对再改 true 真点
    scroll: true,                   // 每轮结束后下滑一屏(养机/信息流常用)
    waitMin: 1500, waitMax: 4000,   // 每轮随机等待(ms),防封,别设固定值
    idleStop: 6,                  // 连续这么多轮啥都没命中就提前收工(0=不停)

    // 模板找图:{名字, base64模板(没有填 null), 搜索区域比例}
    targets: [
      { name: "关注按钮", tpl: null, region: },
      { name: "关闭广告X", tpl: null, region: },
    ],
    // OCR 点字兜底:界面里出现这些文字就点它(换成你 App 的真实按钮文案)
    words: ["关注", "点赞", "下一条"],

    threshold: 0.82,                // 找图阈值,找不到先降到 0.75 再试
};

// ============================ 二、通用函数(可整段复制进工程) ============================
function log(msg) { printl("[" + new Date().getTime() % 100000 + "] " + msg); }// printl 才有输出

function getScr() {
    var s = { w: 1080, h: 2400 };
    try { s.w = screen.getScreenWidth(); s.h = screen.getScreenHeight(); } catch (e) {}
    return s;
}
function rand(a, b) { return Math.floor(a + Math.random() * (b - a + 1)); }
function sleepMs(ms) { try { sleep.millisecond(ms); } catch (e) { java.lang.Thread.sleep(ms); } }

// 点击:无障碍 auto.clickPoint → 全局 click 两级降级(不用HID);runClick=false 时只打印
function doClick(x, y, tag) {
    x = Math.max(1, Math.min(getScr().w - 1, x));
    y = Math.max(1, Math.min(getScr().h - 1, y));
    if (!CFG.runClick) { log("占位不点[" + tag + "] (" + x + "," + y + ") —— runClick=false"); return false; }
    var ok = false;
    try { if (typeof auto !== "undefined" && auto.clickPoint) { auto.clickPoint(x, y); ok = true; } } catch (e) {}
    if (!ok) { try { click(x, y); ok = true; } catch (e) {} }
    log("点击[" + tag + "] (" + x + "," + y + ") ok=" + ok);
    return ok;
}

// 下滑一屏:auto.swip → auto.dispatchGesture 两级降级(无障碍,不用HID)
function doSwipe() {
    if (!CFG.scroll) return;
    var s = getScr();
    var cx = Math.round(s.w * 0.5), y1 = Math.round(s.h * 0.75), y2 = Math.round(s.h * 0.30);
    var ok = false;
    try { if (typeof auto !== "undefined" && auto.swip) { auto.swip(cx, y1, cx, y2, 600, 0); ok = true; } } catch (e) {}
    if (!ok) { try { if (typeof auto !== "undefined" && auto.dispatchGesture) { auto.dispatchGesture(cx, y1, cx, y2, 600); ok = true; } } catch (e) {} }
    log("下滑 (" + y1 + "→" + y2 + ") ok=" + ok);
}

// 找图:★判 null + ★百分比转像素(案例 #02 两条命门都在这)
function findPic(templateB64, regionPct, threshold) {
    if (!templateB64) return null;
    var region = regionPct || ;
    var detects = null;
    try { detects = auto.findImages(, threshold == null ? CFG.threshold : threshold, 0, 1, region); }
    catch (e) { log("findImages异常(当null): " + e); return null; }
    if (!detects || detects.length === 0) return null;          // 命门①:先判空,找不到返回 null 不崩
    var cx = detects.getRect().getCenterX();               // 命门②:这是百分比 0~1
    var cy = detects.getRect().getCenterY();
    var px = screen.percentToWidth(cx), py = screen.percentToHeight(cy); // 必须换算成像素
    return { px: Math.round(px), py: Math.round(py), count: detects.length };
}

// OCR 找字并点击(换分辨率/改版都能点,找图的最佳兜底)
function ocrFindAndClick(word) {
    var img = screen.screenShotFull();
    try {
      var ocr = img.paddleOCR(640, );
      var hit = (ocr && ocr.findIncludeText) ? ocr.findIncludeText(word) : null;
      if (!hit) return null;
      var r = (hit.getRect) ? hit.getRect() : null;
      var x, y;
      if (r) { x = screen.percentToWidth(r.getCenterX()); y = screen.percentToHeight(r.getCenterY()); }
      else { x = null; y = null; }
      if (CFG.runClick) { try { hit.click(); } catch (e) {} }
      return { x: x, y: y };
    } catch (e) { return null; }
    finally { try { img.recycle(); } catch (e) {} }            // 命门③:用完回收
}

// ============================ 三、主循环(真在跑的那段) ============================
function reset() {
    log("复位:回到桌面清残留,再进目标页");
    try { if (typeof auto !== "undefined" && auto.home) auto.home(); } catch (e) {}
    sleepMs(800);
    try { if (typeof back !== "undefined") back(); } catch (e) {}
    sleepMs(500);
}

function oneRound(i) {
    log("— 第 " + i + " 轮 开始(屏 " + getScr().w + "x" + getScr().h + ",runClick=" + CFG.runClick + ")");
    var acted = false;

    // 1) 先按模板找图
    for (var t = 0; t < CFG.targets.length; t++) {
      var tg = CFG.targets;
      if (!tg.tpl) continue;                                 // 没配模板跳过
      var f = findPic(tg.tpl, tg.region, CFG.threshold);
      if (f) { log("找图命中[" + tg.name + "] 共" + f.count + "处 → 像素(" + f.px + "," + f.py + ")"); doClick(f.px, f.py, tg.name); acted = true; }
      else { log("找图未命中[" + tg.name + "](不崩,继续)"); }
    }

    // 2) 找图没中 → OCR 点字兜底
    if (!acted) {
      for (var w = 0; w < CFG.words.length; w++) {
            var o = ocrFindAndClick(CFG.words);
            if (o) { log("OCR命中文字「" + CFG.words + "」→ " + (o.x == null ? "已点(未取坐标)" : "像素(" + o.x + "," + o.y + ")")); acted = true; break; }
      }
    }

    if (!acted) log("本轮没找到任何目标 → 下滑换内容");

    // 3) 下滑 + 随机等待
    doSwipe();
    var wait = rand(CFG.waitMin, CFG.waitMax);
    log("本轮结束,等待 " + wait + "ms 后进入下一轮\n");
    sleepMs(wait);
    return acted;
}

function main() {
    var s = getScr();
    log("========================================");
    log(" 启动 通用找图/OCR点击脚本本机 " + s.w + "x" + s.h + "共 " + CFG.rounds + " 轮");
    log(" runClick=" + CFG.runClick + "(false=空跑只看日志不真点,验证OK再改true)");
    log("========================================");
    reset();
    var idle = 0;
    for (var i = 1; i <= CFG.rounds; i++) {
      var acted = oneRound(i);
      if (acted) idle = 0; else idle++;
      if (CFG.idleStop > 0 && idle >= CFG.idleStop) { log("连续 " + idle + " 轮无命中,提前收工。多半是:目标文字/模板不对,或分辨率变了模板失配 → 见案例 #02 第6节"); break; }
    }
    log("全部结束。");
}

main();


页: [1]
查看完整版本: 通用找图OCR点字完整脚本骨架