木木脚本浏览器 OCR 文字识别功能详解

自动化的核心难题从来不是"点不到",而是"看不到"——网页 DOM 可以用 JS 查询,但 Canvas 画出来的游戏、混淆过的 H5 活动页、图片里渲染的文字,DOM 里什么都没有。木木脚本浏览器内置的 OCR 能力就是为解决"看不到"而生的:让脚本能像人眼一样阅读屏幕,再像人手一样去点击。

一、一行 API:GM_findOcrText

GM_findOcrText(left, top, width, height, callback)
参数 类型 说明
left number 识别区域左上角 x 坐标
top number 识别区域左上角 y 坐标
width number 识别区域宽度
height number 识别区域高度
callback function 异步回调,接收识别结果数组

坐标同样支持归一化(0~1,推荐)像素两种写法。识别是异步进行的,结果通过回调返回。

二、回调数据结构:不只是文字,还有位置

callback 收到的 data 是一个数组,每个元素对应屏幕上的一段文字,且带有完整的位置信息

GM_findOcrText(0.5, 0.5, 0.5, 0.5, function (data) {

    // data 示例:
    // [
    //   { left: 620, top: 1310, x: 700, y: 1340,
    //     width: 160, height: 60, text: '签到' },
    //   { left: 320, top: 1500, x: 400, y: 1530,
    //     width: 160, height: 60, text: '领取奖励' }
    // ]
});
字段 说明
text 识别出的文字内容
left / top 该段文字区域左上角坐标(像素)
width / height 该段文字区域的宽高
x / y 该段文字的中心点坐标(像素)——通常就是你要点击的位置

记住一个关键点:返回的 x/y 是屏幕像素坐标,可以直接传给 GM_click,不需要任何换算。识别 → 点击一气呵成。

三、识别在本地完成

OCR 引擎基于设备端识别方案,识别过程完全在手机本地完成,屏幕内容不会上传到任何服务器

  • 无网络也能识别;
  • 页面上的隐私内容不会因为跑了一个 OCR 脚本而外泄;
  • 没有调用次数限制,脚本可以放心轮询。

如果你有特殊需求(比如需要更强大的云端识别模型),也可以走另一条路:GM_getImage 截图拿到 Base64,再通过 GM_xmlhttpRequest 调用你自己指定的第三方 OCR 接口——浏览器把选择权留给你。

四、区域识别:性能优化的第一原则

GM_findOcrText 的前四个参数划定识别区域。尽量只识别你关心的区域,而不是全屏

// 全屏识别(简单但最慢)
GM_findOcrText(0, 0, 1, 1, cb);

// 只识别屏幕下方 1/4(比如底部按钮区,快得多)
GM_findOcrText(0, 0.75, 1, 0.25, cb);

// 只识别右下角区域
GM_findOcrText(0.5, 0.5, 0.5, 0.5, cb);

区域越小,需要处理的像素越少,识别速度越快、误识别也越少。写脚本前先想清楚:目标文字大概率出现在屏幕哪个位置?

五、内置 OCR 工具:边看边写脚本的调试神器

写 OCR 脚本最大的痛点是"我不知道屏幕上会被识别成什么样"——中文的艺术字体、低对比度文字、图标化按钮,识别结果可能和肉眼所见有出入。

木木脚本浏览器在菜单中内置了 OCR 工具:打开任意网页 → 菜单 → OCR 工具,它会实时识别当前页面,把每段文字的识别结果和区域框直观地标注在屏幕上。

配合开发的工作流是这样的:

  1. 打开目标页面,用 OCR 工具看一眼:目标文字能不能被稳定识别?实际识别出来的字符串是什么(比如全角/半角、有没有多余空格)?
  2. 记下目标文字出现的大致区域,确定 GM_findOcrText 的四个参数;
  3. 回到脚本编辑器写代码,用 indexOf 做模糊匹配(不要用 == 精确匹配整个识别串);
  4. 用菜单中的控制台观察运行日志,必要时用 GM_getImage 保存截图核对。

同菜单里还有一个颜色工具(屏幕取色器),配合 GM_findColor 使用,逻辑相同。

六、实战一:OCR + 点击的自动化闭环

需求:页面出现"领取奖励"按钮时自动点击(该按钮是图片渲染,DOM 里找不到)。

// ==UserScript==
// @name         自动领取奖励
// @namespace    mumudroid.demo.ocr
// @version      1.0
// @description  识别屏幕上的"领取奖励"文字并自动点击
// @match        https://game.example.com/*
// @run-at       document-idle
// ==/UserScript==

(function () {
    'use strict';

    var KEYWORD = '领取';

    function tryGrab() {
        // 奖励按钮通常在屏幕下半部分,只识别该区域
        GM_findOcrText(0, 0.5, 1, 0.5, function (data) {
            if (!data) return;
            for (var i = 0; i < data.length; i++) {
                // 用 indexOf 模糊匹配,容错识别结果中的空格/标点差异
                if (data[i].text.indexOf(KEYWORD) >= 0) {
                    GM_click(data[i].x, data[i].y);   // 坐标直接回传,零换算
                    GM_toast('已领取奖励');
                    return;
                }
            }
        });
    }

    tryGrab();
    // 每 2 秒轮询一次,持续监测新的奖励按钮
    setInterval(tryGrab, 2000);
})();

七、实战二:等待页面就绪再操作

很多 H5 页面加载慢,元素逐个出现。与其固定 setTimeout 猜时间,不如轮询等待目标文字出现

(function () {
    'use strict';

    var retries = 0;
    var timer = setInterval(function () {
        GM_findOcrText(0, 0.7, 1, 0.3, function (data) {
            for (var i = 0; i < data.length; i++) {
                if (data[i].text.indexOf('开始学习') >= 0) {
                    clearInterval(timer);
                    GM_click(data[i].x, data[i].y);
                    GM_toast('检测到目标,已点击');
                }
            }
        });
        if (++retries > 30) {   // 最多等 30 次,避免死循环
            clearInterval(timer);
        }
    }, 1000);
})();

八、实战三:OCR + 滑动 + 找色的组合拳

OCR 不是孤军作战。一个稍复杂的任务(比如"在列表里找到某个带特定颜色标记的条目并点进去")可以这样组合:

(function () {
    'use strict';

    function scanCurrentScreen() {
        // 先用找色快速定位红色"NEW"角标(比 OCR 快)
        GM_findColor('#ff4d4f', 10, 3, 3, 0.5, 0, 0.5, 1, function (pos) {
            if (pos && pos.x) {
                GM_click(pos.x, pos.y);
                GM_toast('发现新条目,已进入');
                return;
            }
            // 当前屏没有红色角标 → 用 OCR 确认是否已经到底("没有更多")
            GM_findOcrText(0, 0.9, 1, 0.1, function (data) {
                for (var i = 0; i < data.length; i++) {
                    if (data[i].text.indexOf('没有更多') >= 0) {
                        GM_toast('已扫描到列表底部');
                        return;
                    }
                }
                // 没到底 → 上滑一屏继续找
                GM_swipe(0.5, 0.7, 0.5, 0.3);
                setTimeout(scanCurrentScreen, 800);
            });
        });
    }

    scanCurrentScreen();
})();

找色负责"快",OCR 负责"懂",滑动负责"翻",点击负责"办"——四类 API 各司其职,这就是木木脚本浏览器屏幕级自动化的典型范式。

九、写 OCR 脚本的几条经验

  1. 缩小识别区域。全屏识别是最常见的性能浪费。
  2. 模糊匹配。用 indexOf / 正则匹配关键词,不要对整段识别结果做全等比较。
  3. 控制轮询频率setInterval 间隔别小于 1 秒,识别本身需要时间,密集轮询没有意义。
  4. 给轮询加退出条件(最大次数 / 找到底部标记),避免页面切走后脚本空转。
  5. 先用内置 OCR 工具踩点,再写代码,能省掉大量"为什么识别不出来"的调试时间。
  6. 文字在深色背景、低对比度、强艺术字场景下识别率会下降,此时可优先考虑 GM_findColor 按颜色定位。

小结

  • GM_findOcrText(区域, 回调):一行 API 让脚本"看懂"屏幕;
  • 结果数组自带每段文字的位置(左上角 + 宽高 + 中心点),坐标可直接传给 GM_click
  • 识别全部在本地完成,不联网、不上传、不限次;
  • 内置 OCR 工具让"人眼"和"机器眼"看到同样的识别结果,脚本调试效率倍增;
  • OCR + 找色 + 滑动 + 点击组合,构成完整的屏幕级自动化闭环。


更多玩法欢迎探索 APP 脚本仓库中的开源脚本;想提功能建议,APP 内"用户反馈"直达开发者。