B2B网络软件

标题: 通用找图OCR点字完整脚本骨架 [打印本页]

作者: YYPOST群发软件    时间: 1 小时前
标题: 通用找图OCR点字完整脚本骨架

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


通用找图OCR点字完整脚本骨架 B2B网络软件

通用找图OCR点字完整脚本骨架 B2B网络软件

通用找图OCR点字完整脚本骨架 B2B网络软件



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

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

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

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

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

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

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

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

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

  74. // OCR 找字并点击(换分辨率/改版都能点,找图的最佳兜底)
  75. function ocrFindAndClick(word) {
  76.     var img = screen.screenShotFull();
  77.     try {
  78.         var ocr = img.paddleOCR(640, [0, 0, 1, 1]);
  79.         var hit = (ocr && ocr.findIncludeText) ? ocr.findIncludeText(word) : null;
  80.         if (!hit) return null;
  81.         var r = (hit.getRect) ? hit.getRect() : null;
  82.         var x, y;
  83.         if (r) { x = screen.percentToWidth(r.getCenterX()); y = screen.percentToHeight(r.getCenterY()); }
  84.         else { x = null; y = null; }
  85.         if (CFG.runClick) { try { hit.click(); } catch (e) {} }
  86.         return { x: x, y: y };
  87.     } catch (e) { return null; }
  88.     finally { try { img.recycle(); } catch (e) {} }              // 命门③:用完回收
  89. }

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

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

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

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

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

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

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

  139. main();
复制代码







欢迎光临 B2B网络软件 (http://bbs.niubt.cn/) Powered by Discuz! X3.2