← 返回首页

屏幕 OCR 加自动点击:把重复操作交给脚本

有些操作每天要做几十遍:等某个按钮出现、点它、等下一屏、再点。眼睛盯着、手在动,脑子完全没参与。这种活最适合交给脚本。

Text_Recognition_Clicker 就是这么来的:Python + PaddleOCR,框选屏幕区域,识别到指定文字就点指定坐标,循环执行,随时能停。

为什么是 PaddleOCR

三个理由:

代价是重。PaddlePaddle 装完几个 G,第一次加载模型要等十几秒。所以脚本启动时加载一次,后面复用同一个引擎实例。

版本锁定这一步别省

这是整个项目最容易卡住的地方。PaddleOCR 的依赖链很挑版本:

pip install paddlex==2.0.0 paddlepaddle==2.4.2

这两个必须配对,Python 也要在 3.8–3.10 之间。用 3.11 或 3.12 会遇到编译好的 wheel 不存在,现场编译基本失败。

装不上不是你的问题,是版本没对上。先固定 Python 版本,再固定 paddle 版本,别倒过来。

区域选择:把「看哪里」变成配置

不让脚本全屏找文字——太慢,而且容易误判。改成先框选区域,运行时只截那一小块。

流程是:点「选择区域」→ 全屏半透明遮罩 → 拖拽出矩形 → 记下 (x, y, w, h) → 保存到配置。运行时 mss 或 PIL.ImageGrab 只截这块,识别量从 1920×1080 降到 300×60,速度快一个数量级。

import mss
from PIL import Image

def grab(region):
    with mss.mss() as sct:
        shot = sct.grab({"left": region[0], "top": region[1],
                         "width": region[2], "height": region[3]})
        return Image.frombytes("RGB", shot.size, shot.rgb)

result = ocr.ocr(np.array(grab(region)), cls=False)
texts = [line[1][0] for line in result[0]] if result[0] else []

文本标准化:空格会害死你

OCR 出来的结果不是你以为的样子。「确认提交」可能被识别成「确 认 提 交」,全角冒号可能变成半角,数字 0 和字母 O 会混。

所以匹配前先做一轮清洗:

import re, unicodedata

def normalize(s):
    s = unicodedata.normalize("NFKC", s)   # 全角 -> 半角
    s = re.sub(r"\s+", "", s)              # 去空白
    return s.lower()

清洗完再用 target in normalized 判断,命中率会从「时好时坏」变成「基本稳定」。

循环、快捷键、停止条件

自动化脚本最危险的不是跑不起来,是停不下来。所以控制逻辑要放在最前面设计:

能力实现
开始 / 暂停F8,用 keyboard 库全局监听
紧急停止F9,立刻跳出循环并释放资源
暂停确认暂停后要求再按一次才恢复,防止误触
循环上限设定最大次数,跑满自动停
停止条件监控一个区域,出现指定文本就终止

「暂停-确认-恢复」这个设计看起来多余,实际很必要:手滑按到 F8 之后,脚本如果立刻继续点,可能已经点错了三下。

稳定性靠间隔,不靠运气

两类间隔必须能配:

给太短,界面还没反应过来,脚本已经在点下一屏;给太长,效率还不如手动。我的经验是先从 0.8 秒起步,跑三轮没问题再往下压。

另外每个动作都包在 try 里,异常记日志但不停机——单次识别失败不该让整轮白跑。

边界

这类工具只适合自己有权操作的界面:自己的软件、自己的账号、允许自动化的流程。它本质上是在模拟人手,不是绕过什么。

真要上线之前,先跑一遍「只识别不点击」的干跑模式,看清楚它到底认到了什么。很多问题在这一步就能发现,不用等它点错地方。

← 上一篇:从零开始 下一篇:零依赖静态站 →