iOSOCR脚本开发

脚本识别文字然后点击,坐标从哪来

脚本识别文字然后点击,卡住的往往是坐标那一步。ocrImage 返回的 x、y 是文字框左上角,直接点会偏出半个字高,要加半个宽高才是中心。

约 7 分钟

翻文档的时候,我想找的是「识别到文字怎么点下去」。ocrImage 那一节写得挺全,参数、超时、返回值都有,示例代码最后一行打印了四个数。

logd("文字 " + value.label + " confidence " + value.confidence
     + " range " + value.x + "," + value.y + ","
     + (value.width + value.x) + "," + (value.height + value.y));

x、y、x 加 width、y 加 height。四个数画出一个矩形,左上角和右下角。文档到这儿就结束了,没提后面该点哪儿。

第一次看这段示例,我默认 x、y 就是能点的点,拿到就往 clickPoint 里塞。错了,落点在文字框左上角那个顶点上。按钮要是圆角的,这一下就空了;文本越长越明显,height 越大,左上角离中心越远。

脚本识别文字然后点击这件事,难的就是中间这一步。识别准了、坐标拿到了,点不中还是白搭。这也是大多数人写文字识别脚本时卡住的地方;前面识别、后面点击,两个都能单独跑通,接起来就不对。

文档给的矩形怎么变成能点的点

中心很好算,x 加半个宽,y 加半个高。难的是知道要这么算,因为文档里没有这一步。

有人问脚本点击坐标怎么设置。要设的其实只有屏幕尺寸那一次,剩下的偏移都是算出来的。

let cx = v.x + Math.floor(v.width / 2);
let cy = v.y + Math.floor(v.height / 2);

拿「确认」按钮举例,x 是 320、y 是 1180、宽 120、高 48。算出来 380 和 1204,这个点落在按钮正中。

矩形画出来的是文字占的位置,能点的中心要自己算。这两件事在 OCR 里被合成一个返回值,所以容易混。找图的返回结构不一样,那边给的是 left、right、top、bottom,左右取中、上下取中;算法完全不同。两个模块的文档分在两个文件里,同时看到的人不多。

一次识别通常返回好几条。页面上的标题、按钮、提示语全在里面。得靠 label 匹配再加上 confidence 过滤才挑得出来。

一段能抄的写法

function clickText(tocr, target, retry = 3) {
    for (let i = 0; i < retry; i++) {
        let img = image.captureFullScreenNoAuto();
        if (img == null) {
            sleep(500);
            continue;
        }
        let res = tocr.ocrImage(img, 10 * 1000, {"matMode": 1});
        image.recycle(img);

        if (res && res.length > 0) {
            let hit = res.find(v =>
                v.label.indexOf(target) >= 0 && v.confidence >= 0.8
            );
            if (hit) {
                usbHidEvent.clickPoint(
                    hit.x + Math.floor(hit.width / 2),
                    hit.y + Math.floor(hit.height / 2)
                );
                return true;
            }
        }
        sleep(800);
    }
    return false;
}

image.recycle(img) 千万别漏。截图对象不回收,占的是手机内存;跑一批 30 台设备、每台几十轮,涨得挺快。

超时给了 10 秒。第二个参数就是毫秒,跑满才返回空。文档示例里写的是 30 秒,照抄下来,界面明明没出来也要干等半分钟。

置信度卡在 0.8。太低会把「确认」认成「确以」,点了没用;太高可能一个都匹配不上。七成到八成五之间比较稳,界面文字清楚就往高取。我试过 0.95,连确认按钮都匹配不出来,又退回 0.85。

截图要用 captureFullScreenNoAuto,别用 captureFullScreen。前者不需要开自动化,配合 USB HID 全程不用装 App。这条路径从 EC iOS USB 10.7.0 起提供,手机要 iOS 17 及以上;代价是慢一点,文档里也写了。

两个函数名太像,改脚本时容易顺手写错一个。写错了不报错,只是慢,或者截图失败。

调用的时候前面还得开会话和初始化。

function main() {
    let r = usbHidEvent.sessionStart(true);
    if (r != null && r != "") { logw("会话失败 " + r); return; }
    usbHidEvent.setScreenSize(1170, 2532);

    ocr.releaseAll();
    let tocr = ocr.newOcr();
    if (!tocr.initOcr({"type": "appleVision", "level": "accurate",
                       "languages": "zh-Hans"})) {
        loge("初始化失败 " + tocr.getErrorMsg());
        return;
    }

    if (clickText(tocr, "确认")) {
        sleep(1500);
    }
}

releaseAll 要放在 newOcr 前面。上一次没释放干净的实例会占着内存,一个脚本里反复调用时特别明显。

点不动的时候,先从识别结果里找原因

日志里能看到 confidence,先看这个数。

列表页有好几个「查看」,find 只拿第一个,往往是最上面那个,不是你要的。两个办法,截图前把区域裁到目标附近,用 image.clip 缩小范围;或者按 y 坐标排一下序再取第几个。

识别到了但点不动,多半是置信度太低。七成以下的结果,label 本身就是错的,点下去当然没反应。

还有一种,OCR 返回空,但截图是好的。界面刚切过去,动画还没结束,截到的图是模糊的;加个 sleep 等动画走完,比提高重试次数管用。

这三种都是「识别到了,但用不上」。市面上的文字识别点击器大多识别一下就点,不判断。要做成识别文字自动点击,判断条件得比识别本身更严;写自动点击脚本就得自己扛这一层。

常见问题

x、y 能直接点吗?

不能。那是文字框左上角,要加半个宽高才是中心。

多个同名结果怎么选?

裁剪截图缩小范围,或按 y 排序后取指定序号。find 永远只返回第一个匹配。

OCR 每次都要初始化?

不用。脚本开头一次就够。不过正式任务里 OCR 较多时,任务结束后引擎会释放,下次同类任务第一步可能多等几秒。

不开自动化能用吗?

能。captureFullScreenNoAuto 不需要自动化环境。配合 USB HID 点击,全程不装代理 IPA。


iEasyClick 是手机自动化 AI 智能体平台,覆盖安卓免 root、iOS 免越狱(代理/蓝牙 HID/OTG HID)、鸿蒙 Next 三大生态,提供脚本开发、苹果群控、本地中控投屏与云控系统。→ 了解全部产品

想要真实跑起来?

本文介绍的方案均可基于 EasyClick 能力在 iEasyClick 落地。官网提供完整文档、开发工具与自动化产品,免费体验。

访问 iEasyClick 官网 →