做自动化的朋友应该都遇到过这种时刻:屏幕上明明有字,但脚本就是读不出来。控件识别识别不了自绘窗口,找图找色遇到抗锯齿字体就拉胯。我前前后后在好几个项目里试过本地识别、词库匹配,最终发现最适合自动化的还是接云端的 OCR 文字识别 API。这篇教程把按键精灵调用 OCR 的完整链路讲一遍,从申请密钥、拿到 Token,到真正把图片转成文字、把文字写回脚本,每一步都给了可跑的脚本,适合刚接触按键精灵和 API 的新手,也适合被各种识别问题卡住的进阶用户。
1. 为什么要在按键精灵里接OCR:场景与方案选型
按键精灵本身的优势是模拟鼠标键盘、控制窗口焦点,但它的“读字”能力一直不算强。很多人一开始都在用控件识别,也就是通过窗口句柄、控件类名、控件内容去读取界面文本,这套方法在面对标准 Windows 窗口时很好用,但遇到自绘窗口、网页渲染区域、游戏界面或者一些壳套得很深的业务软件时,控件树根本拿不到。鼠标点上去明明能选中文字,脚本里却永远是空的。这时候如果去找客服要接口,对方不一定给;自己硬啃窗口句柄,效率又特别低。
换用找图找色的思路也能做,但本质上是在做模板匹配。先截一张带字的图作为字库样本,然后在屏幕区域里逐点匹配。问题在于文字一旦换了字体、字号、颜色或者背景出现渐变,匹配率就会断崖式下降。我最早做一套订单号采集的时候,就是靠找图找色去定位行号,结果页面从宋体换成雅黑,整套字库全部失效,光是重新做字库就花了两天。后来我干脆放弃纯图像方案,转向 OCR,把“读字”这件事交给真正的文字识别模型去做,脚本只负责截图和处理结果,一下子就顺了。
云端 OCR API 的好处在于,模型已经帮我们把识别、纠错、排版还原都做完了。你不需要懂计算机视觉,不需要维护训练数据,只需要把图片编码成 Base64 发过去,再解析返回的 JSON。识别接口的并发和额度通常也够自动化脚本使用,比起本地 OCR 方案,接入成本和维护成本都低得多。当然代价也很明确:必须联网,且涉及隐私的图片不能随意上传。所以我在实际项目里会先问一句:这图里有没有敏感信息?如果没有,走云 API 就是最优解。
1.1 按键精灵的文字获取困境
按键精灵在设计之初就不是一个“图像理解”工具。它擅长的是按坐标点击、按窗口标题切换、按像素颜色判断状态,这些都是可枚举、可预判的操作。但屏幕上的文字是语义信息,想用坐标和颜色去表达“这句话里有什么”,本质上是在用穷举法解决语义问题。穷举法遇到可控环境还行,比如固定软件、固定字体、固定背景,但真实自动化任务里,稍微弹个窗、换个文本颜色,之前的规则就全部失效。
我自己踩过最典型的坑是在一个后台管理页面上抓取用户备注。网页里那些文字在 DOM 里明明存在,但按键精灵的网页控件识别经常拿不到嵌套层级比较深的文本,用抓词命令又只能在 IE 内核里生效,换到 Chrome 内核直接抓瞎。后来我改了思路:不追求读到 DOM,而是把整个区块截图下来,用 OCR 把文字认出来。这样浏览器内核是什么根本无所谓,只要屏幕上能看到字,我就能拿到字。
所以在这个阶段,不要把“读字母”寄托在控件识别上,尽可能把目标区域当图片处理。截图 + OCR 的组合,是按键精灵场景下兼容性最高的读字方式。
1.2 为什么是云端OCR API而不是本地识别
本地识别不是不能跑,我也试过开源的 Tesseract 和几个本地识别框架,问题都出在中文和版式上。Tesseract 对印刷体英文和数字识别效果还算可以,一旦遇到中文、带边框的表格、有底色的文字,识别率就会明显下降,需要额外训练语言包和字库。训练字库是个持续投入的活,你做两三个字体可能还能撑,字体一多就崩。而且本地识别在按键精灵里集成也很麻烦,要么调用外部命令行,要么封装 DLL,对普通脚本用户不太友好。
云端 OCR API 则直接把最成熟的模型开放出来,识别准确率、多语言支持、表格还原都是现成的。接入这一侧以后,脚本的所有负担就只剩两件事:怎么把截图送过去,怎么把返回的文字取出来。我倾向于把复杂计算交给专业服务,按键精灵只做调度和业务判断。毕竟 OCR 模型不是我们的核心竞争力,自动化流程才是。
当然,云端方案也有短板。首先是隐私问题,上传到外部接口的图片不经过脱敏就不能乱传,一些内部系统截图、订单含客户信息的截图,我一般会先做好打码或者干脆不用外部接口。其次是稳定性,网络抖动、服务商限流都会导致超时,脚本里必须做重试和异常兜底。但这些问题都比较容易通过工程手段解决,相比自己维护识别模型,性价比还是高很多。
1.3 适用场景和使用边界
实际用下来,云端 OCR API 比较适合以下几类场景:验证码里的数字字母识别(注意是普通验证码,不是专门的反爬验证码)、聊天窗口和社交软件里的文本采集、网页后台的订单号/金额/状态提取、截图日志里的错误信息抓取,以及一些简单的票据和表格内容整理。
不适合的场景主要有这几类:完全断网的环境、需要每秒钟识别几十张的高并发场景、图片内容涉及核心敏感数据且无法脱敏的场景。如果你身处断网环境,建议老老实实做本地字库;如果是高并发,也可以考虑本地化部署模型,但那就是另一个量级的工程了。对绝大多数按键精灵用户来说,一天几十到几百次的识别量,云端 API 的额度完全够用,不需要自己折腾模型。
| 方案 | 原理 | 优势 | 短板 |
|---|---|---|---|
| 控件识别 | 读取窗口控件属性 | 速度快、无网络依赖 | 自绘界面和网页拿不到 |
| 找图找色 | 逐像素模板匹配 | 简单直接 | 字体背景一变就失效 |
| 本地OCR | 本地模型识别 | 可离线、数据可控 | 中文版式训练成本高 |
| 云端OCR API | 服务端模型识别 | 识别率高、接入简单 | 需联网、有配额限制 |
2. OCR API的底层原理与接入准备
很多人第一次接触 OCR API 会觉得流程很绕:明明只是传一张图,为什么还要先换一个 Token?这里可以打个比方。API Key 和 Secret Key 是你的长期工牌,Access Token 是临时访客证。你不能拿着工牌到处刷每一个门禁,而是先到前台用工牌换一张访客证,然后在一定时间内凭证进出各个会议室。这样服务商可以统一控制权限和有效期,也能在令牌泄露时单独吊销,不至于动到核心凭证。
一次完整的 OCR 调用,数据流大致是这样的:客户端先携带 API Key 和 Secret Key 请求鉴权接口,服务端验证通过后返回 Access Token;客户端再把待识别图片读取为字节流,转成 Base64 字符串;随后把 Base64 和识别参数一起提交到文字识别接口;识别接口返回一段 JSON,里面包含识别出来的文字、置信度、坐标这些信息。最后脚本解析 JSON,提取自己需要的字段。
这个流程里的每一步都不复杂,但有一个关键细节:Access Token 是有有效期的,常见的是几天到一个月不等,而且拿到 Token 后不应该每次识别都重新获取。把 Token 缓存到本地文件,只在过期时刷新,这样既省网络请求,也降低被限流的概率。
2.1 一次OCR调用的完整数据流
放一个更详细的顺序图出来,在脑子里过一遍:
- 使用 API Key 和 Secret Key 调用 Token 接口,参数通常是
grant_type=client_credentials。 - 从返回 JSON 中取出
access_token和expires_in。 - 把
access_token和过期时间保存到本地或内存。 - 读取图片文件,转换为 Base64 字符串。
- 调用识别接口,URL 上携带
access_token,请求体里携带image字段。 - 接口返回
words_result数组,每个元素包含words字段,这就是识别出的文字。 - 脚本把数组中所有
words拼接成文本,输出给后续逻辑使用。
这个流程和大多数 OCR 服务商的接口设计是兼容的。哪怕你实际使用的平台参数名略有不同,整体顺序也不会变。我习惯先在调试工具里手动跑通一遍,再把这些步骤搬到脚本里,可以省下大量排错时间。
2.2 准备账号密钥:创建应用与获取凭证
不同云平台的 Console 界面不一样,但创建“文字识别应用”的路径基本一致。常见流程是:注册账号并完成实名认证,进入控制台后创建一个应用或项目,在应用的管理页里选择“文字识别”服务,开通后就能看到一组 API Key 和 Secret Key。有些平台还会提供一个额外的 App ID,一般用不到,但不要弄丢。
申请密钥时我建议注意三件事。第一,密钥创建后一定要自己存好,很多平台只在创建时完整展示一次,之后就无法再查看完整 Secret Key,只能重新创建。第二,密钥不要直接写在按键精灵脚本里到处发,至少放到一个独立配置文件里,或者使用变量引用。第三,有些平台允许配置 IP 白名单,如果你在办公室和家里切换网络,别把白名单限制太死,否则脚本一换环境就会鉴权失败。
开通服务后先去看一下免费配额和 QPS 限制。大部分平台每天都会送几百到几千次免费识别,单次并发限制通常每秒几次,这对按键精灵脚本来说基本够用。我见过有人没看配额,脚本循环里跑得太快,几分钟就把额度打光,后面一整天全部报错。正确做法是先算好自己每天的识别量级,再决定是白嫖免费额度还是购买资源包。
2.3 接口选择与参数说明
OCR 接口通常分通用文字识别、高精度识别、专用识别三类。通用识别适合普通截图、文档、聊天记录,速度较快;高精度识别适合复杂背景或者图文混排,但速度更慢,成本也更高;专用识别则针对特定场景,比如车牌、银行卡、营业执照。对于按键精灵的大部分自动化需求,选通用文字识别即可,识别率和响应速度最均衡。
以通用的识别接口为例,常用参数大致如下:
| 参数 | 是否必填 | 说明 |
|---|---|---|
| image | 是 | 图片的 Base64 字符串,有些平台也支持传 URL |
| language_type | 否 | 语言类型,常用中文混合,默认通常已包含 |
| detect_direction | 否 | 是否检测图片方向,适合拍摄歪斜的图片 |
| paragraph | 否 | 是否返回段落信息,表格类内容可以开 |
| probability | 否 | 是否返回置信度,需要过滤低质量结果时开启 |
接口返回的 JSON 结构通常是{"words_result": [{"words": "识别内容"}, ...]}。不同厂商字段名可能略有差异,但大体一致。我在脚本里就是基于这个结构去解析的,如果你用的服务商字段名不同,只要把代码里对应的字段替换一下就行。
3. 从申请密钥到首次请求:打通工具链
在做按键精灵脚本之前,我强烈建议先用接口调试工具把请求通一遍。这一步能帮你确认三件事:密钥是否正确、请求地址是否写对、返回结构是否和你预期一致。很多人上来就把代码写进按键精灵里,结果报错之后根本分不清是脚本问题还是接口问题,排查起来非常痛苦。
调试时建议分两步走。第一步先调 Token 接口,确认能拿到access_token;第二步再带着 Token 调识别接口,确认能识别图片并返回文本。两步都通了,再搬进按键精灵,这时候剩下的问题就只有按键精灵侧的命令细节了。
3.1 用API在线调试工具验证
打开你习惯的接口调试工具,新建一个 POST 请求。Token 接口的地址填成服务商提供的 OAuth Token 端点,参数格式选择application/x-www-form-urlencoded,然后填写grant_type=client_credentials、client_id和client_secret。发送后如果密钥正确,会看到返回 JSON 里有一个access_token字段,还有一个expires_in表示有效期秒数。
接着调试识别接口:把 Token 拼在 URL 的access_token参数上,请求体用表单格式,image字段填图片的 Base64。你可能会问字符串那么长怎么手动填?我一般用一个最简单的 PowerShell 命令把图片转成 Base64,然后把输出复制到调试工具里。第一次跑通后你会对返回的words_result结构有直观印象,后面再写解析逻辑就很轻松。
调试这一步最容易犯的错误,是把 Secret Key 和 Access Token 搞混。Token 接口用的 Secret Key 是创建应用时的那串长密钥,识别接口用的 Access Token 是 Token 接口返回的临时凭证,两者不是同一个东西。如果搞混了,报错永远是鉴权失败。
3.2 获取访问令牌(Access Token)
大多数云 OCR 平台的鉴权采用 OAuth2 的客户端凭证模式,逻辑很简单:把 API Key 和 Secret Key 提交到 Token 接口,换取 Access Token。这里我直接用 PowerShell 写一个最小示例,你在正式脚本里可以照抄:
$tokenUrl = "https://api.your-ocr-platform.example.com/oauth/2.0/token" $body = "grant_type=client_credentials&client_id=你的APIKey&client_secret=你的SecretKey" $resp = Invoke-RestMethod -Uri $tokenUrl -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body $token = $resp.access_token $expires = $resp.expires_in Write-Host "Token: $token" Write-Host "Expires: $expires"正常返回的内容里会有一个expires_in,单位是秒,常见值是 2592000,也就是 30 天。拿到 Token 后不要每次都重复请求,要把它缓存起来。缓存的意义不只是省流量,更重要的是避免频繁调用 Token 接口触发服务商的频率限制。等正式脚本里我会用本地文件保存 Token 和过期时间。
3.3 构造图片识别请求(Base64与JSON)
把图片发送给 OCR 服务时,图片本身是二进制文件,直接在 HTTP 请求里传输容易丢失,所以行业标准做法是把图片转成 Base64 字符串。Base64 本质是用 64 个 ASCII 字符重新编码二进制数据,转换后的体积会比原图增加约三分之一,好处是传输稳定、不容易被转义破坏。
在 PowerShell 里转 Base64 很简单:
$bytes = [System.IO.File]::ReadAllBytes("C:\auto_ocr\tmp.png") $base64 = [Convert]::ToBase64String($bytes)然后把$base64作为请求体里的image字段提交。注意两件事:第一,有些服务商要求 Base64 不能带有data:image/png;base64,这样的前缀,要先把前缀去掉;第二,如果你的图片超过了接口限制的大小,通常超过 4MB 或者长边超过 4096 像素,就必须先压缩,否则接口会报错。
由于图片转 Base64 后字符串可能很长,如果用某平台的 JSON 格式提交,需要把image字段放进 JSON 对象里。如果用的是我后面的脚本里那种表单格式,PowerShell 的Invoke-RestMethod会自动处理 URL 编码,所以我们只需要拼好$body = "image=$base64"就可以。
4. 按键精灵实战:从脚本到可复现
到这里,接口层已经通了,接下来就是把请求逻辑嵌进按键精灵的自动化流程里。按键精灵本身没有一个完全统一的 HTTP 命令,不同版本、不同插件对 HTTP 的支持方式都不一样,这也是很多教程容易翻车的地方。我在实战中选了更稳妥的一条路:用系统自带的 PowerShell 脚本发请求,按键精灵负责截图和调度。
4.1 两种接入方式对比:插件方案还是 PowerShell 桥接
如果你已经用过按键精灵的 HTTP 插件,那可以直接在脚本里写Plugin.Http.Post这类命令,好处是无需跳出按键精灵,响应也快,适合对插件比较熟的人。但问题是插件命令写法五花八门,有的插件用Http.Post,有的插件用Web.Post,带着不同参数格式,新手照着教程抄很容易被插件版本卡住。
PowerShell 桥接方案就简单得多:系统自带 PowerShell,不需要额外装插件;请求逻辑用标准 PowerShell 写,可以单独调试;按键精灵只负责截图、调用、读文件,职责非常清晰。代价是每次运行都要启动一个 PowerShell 进程,耗时比插件方案多一两百毫秒,但对 OCR 识别这种本身就要几百毫秒的操作来说,完全可以忽略。
| 方式 | 优点 | 缺点 |
|---|---|---|
| HTTP插件方案 | 集成度高、响应快 | 依赖插件版本、命令差异大 |
| PowerShell桥接 | 不依赖插件、可独立调试 | 每次启动稍慢、需要处理临时文件 |
我的完整脚本采用 PowerShell 桥接。如果你已经有能用的 HTTP 插件,只需要把脚本里的请求部分替换成对应插件命令,其他逻辑仍然适用。
4.2 完整 PowerShell 识别脚本
下面这个脚本就是我目前在用的原型,功能包括:获取 Token、缓存 Token、读取图片转 Base64、调用 OCR 识别接口、把识别文字写入结果文件。把它保存为ocr_cloud.ps1,放在固定目录下。
param( [string]$ImagePath, [string]$ApiKey, [string]$SecretKey, [string]$ResultFile = "$PSScriptRoot\ocr_result.txt", [string]$TokenCacheFile = "$PSScriptRoot\token_cache.txt" ) $ErrorActionPreference = "Stop" # 服务商接口地址,请替换成你的实际地址 $tokenUrl = "https://api.your-ocr-platform.example.com/oauth/2.0/token" $ocrUrl = "https://api.your-ocr-platform.example.com/rest/2.0/ocr/v1/general" function Get-AccessToken { $cache = @{} if (Test-Path $TokenCacheFile) { try { $cache = Get-Content $TokenCacheFile -Raw | ConvertFrom-Json } catch { $cache = @{} } } if ($cache.access_token -and $cache.expire_time) { $expiresAt = [datetime]::Parse($cache.expire_time) if (Get-Date -lt $expiresAt) { return $cache.access_token } } $body = "grant_type=client_credentials&client_id=$ApiKey&client_secret=$SecretKey" $resp = Invoke-RestMethod -Uri $tokenUrl -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body $expireTime = (Get-Date).AddSeconds($resp.expires_in - 60) @{ access_token = $resp.access_token; expire_time = $expireTime.ToString("o") } | ConvertTo-Json | Set-Content -Path $TokenCacheFile -Encoding UTF8 return $resp.access_token } $token = Get-AccessToken $bytes = [System.IO.File]::ReadAllBytes($ImagePath) if ($bytes.Length -gt 4194304) { throw "图片超过4MB,请先压缩或裁剪后再识别" } $base64 = [Convert]::ToBase64String($bytes) $body = "image=$base64" $headers = @{ "Content-Type" = "application/x-www-form-urlencoded" } $ocrResp = Invoke-RestMethod -Uri "$ocrUrl?access_token=$token" -Method Post -Headers $headers -Body $body $lines = @() foreach ($item in $ocrResp.words_result) { $lines += $item.words } $resultText = $lines -join "`r`n" Set-Content -Path $ResultFile -Value $resultText -Encoding UTF8先说 Token 缓存逻辑。脚本会先看本地有没有token_cache.txt,如果文件存在且有没过期的 Token,就直接复用;如果过期或不存在,就重新请求 Token,并把新的 Token 和过期时间写回文件。expires_in - 60的意思是提前一分钟过期,避免刚好在有效期边界上请求失败。
再看图片处理。ReadAllBytes把图片读成字节数组,Convert.ToBase64String转成 Base64。如果图片超过 4MB,直接抛错,因为很多接口只接受 4MB 以内的图片。如果你需要识别的截图比较大,可以先在按键精灵侧把截图区域缩小,或者先用图片处理命令压缩一下。
最后是结果解析。调用识别接口后,返回的 JSON 会被 PowerShell 自动转成对象,$ocrResp.words_result是一个数组,每一项都代表一块识别出来的文字。脚本把每个words字段取出来,用换行符拼成一个完整的文本,然后写入结果文件。
4.3 按键精灵调用脚本并读取结果
PowerShell 脚本准备好之后,按键精灵侧就非常简单了。大致流程是:先截图保存成 PNG,然后通过RunApp启动 PowerShell 执行识别脚本,等待几秒后读取结果文件。下面是一个最小示例:
// 1. 截图指定区域并保存 Plugin.Prtsc.Capture 100, 100, 500, 300, "C:\auto_ocr\tmp.png" // 2. 调用 PowerShell 识别 RunApp "powershell.exe -ExecutionPolicy Bypass -NoProfile -File ""C:\auto_ocr\ocr_cloud.ps1"" -ImagePath ""C:\auto_ocr\tmp.png"" -ApiKey ""你的APIKey"" -SecretKey ""你的SecretKey"" -ResultFile ""C:\auto_ocr\result.txt""" // 3. 等待识别完成 Delay 3000 // 4. 读取结果文件(命令以你的按键精灵文件插件为准) Dim ocrText ocrText = Plugin.File.ReadFileEx("C:\auto_ocr\result.txt") TracePrint ocrText这个示例里最容易出问题的是RunApp的双引号嵌套。按键精灵字符串里连续两个双引号表示一个真正的双引号,所以""C:\auto_ocr\ocr_cloud.ps1""的实际效果是给路径加了一个命令行引号。如果你的路径没有空格,也可以直接去掉这些边界引号,写成更短的形式。
Plugin.Prtsc.Capture是截图插件的示例命令,不同按键精灵版本的截图命令名称可能不同。你只要把目标区域截图保存到一个文件即可。截图后调用 PowerShell 脚本,脚本完成识别并把结果写入result.txt,之前的Delay 3000是简单粗暴地等 3 秒,建议在正式项目里改成轮询文件直到出现内容。
读取结果文件我写的是Plugin.File.ReadFileEx,这是按键精灵常见文件插件的一个命令。如果你的按键精灵里没有这个命令,打开“插入命令-文件”看一下,选择对应的读取文本命令即可。核心思路不变:把 PowerShell 写好的文本文件读出来,交给按键精灵继续处理。
4.4 识别结果解析与编码处理
在 PowerShell 脚本里,解析识别结果的逻辑其实只有几行:遍历$ocrResp.words_result,把words字段拼起来。因为接口返回的是数组,所以文本的顺序就是从左到右、从上到下的排列,基本符合人类阅读习惯。
这里有一个非常容易踩的坑:编码。PowerShell 脚本写入结果文件时用的是 UTF8,而按键精灵如果按默认 ANSI 编码读取文本,遇到中文就会乱码。解决思路是两种:让 PowerShell 输出 ANSI 编码,或者让按键精灵按 UTF8 读取。我更推荐后者,因为 UTF8 兼容性更好,也方便后续把文本传给其他程序。如果你手里的文件插件不支持指定编码,就在 PowerShell 写入时改成 ANSI 编码,比如Set-Content -Encoding Default,但要注意这样只能保证在当前中文系统里正常。
如果识别出来的结果里混着多余的空行,多半是接口对版面中的空白区域也返回了空字段。可以在拼接的时候过滤掉空字符串:if ($item.words) { $lines += $item.words }。这个小细节在识别带有大量留白的截图时能明显提升脚本后续处理的准确度。
5. 常见报错与排查技巧实录
不管接口文档写得多清楚,实际跑起来总会有各种意外。下面这些报错是我在项目里真实遇到过的,把每一个的排查路径列出来,你可以直接当速查表用。
5.1 鉴权失败:密钥没生效
常见的失败提示有invalid_client、invalid_grant、401 Unauthorized。这类问题十有八九是密钥复制错了,或者 Token 已经过期。排查方法很简单:先在调试工具里单独请求一次 Token 接口,如果能拿到access_token,说明密钥本身没问题;如果拿不到,就要检查密钥最后一串字符是不是漏了、复制时是不是带了多余的空格。
还有一种隐蔽情况,就是服务商开启了 IP 白名单。你在办公室能通过,回到家网络环境变了就报鉴权错误。这时候去控制台把当前网络的出口 IP 加进白名单,或者直接关闭白名单功能。另外别忘了,Token 缓存文件如果过期,脚本应该自动去重新获取。如果你手动删除了token_cache.txt后脚本恢复正常,说明问题就出在 Token 缓存逻辑上。
密钥管理方面,我的建议是不要把真实密钥写死在按键精灵代码里。先用一个文本文件存密钥,按键精灵读取文件后作为变量传给 PowerShell。这样即使脚本文件被人看到了,核心密钥也能少一份暴露风险。
5.2 图片参数与接口限制
| 报错现象 | 可能原因 | 处理办法 |
|---|---|---|
| image format error | Base64错误或图片格式不受支持 | 确认图片是 jpg/png/bmp,确认Base64没有多余前缀 |
| image too large | 超过接口大小限制 | 压缩图片或缩小截图区域 |
| qps request limit reached | 请求频率超过并发额度 | 在循环里加延时,减少同时请求数 |
| timeout | 图片太大或网络不稳定 | 裁剪截图、压缩图片、增加超时时间 |
图片格式错误是个很典型的新手问题。很多人在调试工具里能识别,搬到脚本里就失败,原因是手动转的 Base64 和脚本转的 Base64 不一致。检查时重点看字符串开头:有些平台要求不带data:image/png;base64,前缀,有些要求必须带,需要根据服务商文档来。另外确认你读的文件确实存在,而且扩展名和真实格式一致。比如你把一个 JPEG 文件改名成.png,某些严格的接口会返回格式错误。
图片太大导致的超时也很常见。我处理这类问题的方法是:先看截图区域是不是包含了大量空白区域,如果是,直接在按键精灵里缩小截图范围;如果图片内容本身很复杂没有多余空白,就用图片处理命令把图压缩到 1000 像素宽度以内再转 Base64,识别率通常不会下降太多。
5.3 按键精灵命令兼容性
按键精灵版本差一点,命令就差很多。我用的是最常见的插件调用方式,你的环境里可能没有Plugin.Prtsc.Capture或者Plugin.File.ReadFileEx。不要硬背命令,打开按键精灵的“插入命令”面板,找到对应的插件,看它的命令名和参数,替换成你本机的即可。
如果RunApp调用了 PowerShell 但没反应,先检查执行策略。Windows 默认可能不允许脚本执行,需要给 PowerShell 加上-ExecutionPolicy Bypass参数。如果还是不行,把powershell.exe换成完整路径,例如C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,这样能避免环境变量导致的调用失败。
最后一种情况是结果文件等了很久还是空的。不一定是 OCR 慢,很可能是 PowerShell 脚本报错后窗口一闪而过。这时候手动在命令行里把ocr_cloud.ps1的参数跑一遍,看控制台输出的错误信息,问题一般就出现在密钥、路径或网络这三者之中。
6. 性能优化与生产建议
脚本能跑通只是第一步,真正要稳定地跑在生产环境里,还需要做几件小事。这些东西不是接口文档会写清楚的,但都是我在实际项目里反复调过之后总结出来的经验。
6.1 token 缓存与复用
我在前面已经给出了 Token 缓存实现,这里再解释一下为什么要在expires_in上减 60 秒。原因很简单:当你使用本地文件缓存 Token 时,文件写入时间和实际过期时间之间存在误差;如果刚好在你请求的那一秒过期,服务端会返回无效 Token,脚本就必须多走一次重试。提前一分钟失效,可以避开这种边界情况。
如果你是直接跑到按键精灵脚本里的 HTTP 插件方案,不写文件缓存,而是把 Token 保存在按键精灵全局变量里。优点是同一进程内复用更快,缺点是找不到 Token 时无法确认它是否过期。所以用变量缓存时,要在第一次获取 Token 后记录获取时间和有效期,每次调用前判断一下当前时间是否接近过期时间。
6.2 截图预处理提升识别率
OCR 对图片质量其实很挑剔。同样是识别一段文字,直接截全屏的效果往往不如只截文字区域,因为多余的背景会干扰模型。所以截图前先想清楚:我要的文字在哪个位置,截图范围能不能缩到最小。区域越干净,识别率越高,响应速度也越快。
对于背景复杂的界面,可以尝试在按键精灵里做一层简单预处理:先把图片放大 2 倍,再用图像处理命令做灰度化或者二值化。OCR 模型对高对比度的图像更友好,放大后的文字边缘也更清晰。需要注意的是,放大图片会增加 Base64 体积,如果服务商有 4MB 限制,就要在放大和压缩之间找一个平衡点。
我的经验是,文字颜色和背景颜色差异越大,识别效果越好。如果截出来的图是深色背景浅色文字,有些 OCR 模型也能识别,但稳定度不如浅色背景深色文字。遇到这种界面,可以先用按键精灵的图像处理功能反色,再提交识别,往往会有惊喜。
6.3 后续扩展思路
这个框架一旦跑通,想扩展就很容易。你可以做一个固定区域的轮询脚本:每隔几秒截一次图,识别文字,当文字内容发生变化时触发鼠标或键盘动作。这个模式非常适用于检测弹窗、读取系统状态、自动记录交易结果等场景。
还可以把 PowerShell 脚本改造成批量模式,传入一个文件夹路径,自动识别文件夹里所有截图,把结果汇总成一个文本文件。这样你就能利用按键精灵定时截图,然后再用 OCR 做离线分析,不需要在页面停留太久。
重试机制也值得加进去。OCR 请求失败时,先判断错误类型。timeout和qps类错误可以延迟 2 秒重试,最多三次;invalid_client这种鉴权错误则不要盲目重试,先检查密钥。把这些逻辑做成一个循环,脚本在无人值守时也能稳定运行。
我个人实际跑这种方案时,最省事的不是把所有逻辑都塞进按键精灵,而是让 PowerShell 管网络请求、按键精灵管界面调度。两者各干各的,出问题时定位也快。如果你也想搭一套稳定读字的自动化,建议先在调试工具里把接口调通,再搬进脚本;一次只加一个变量,抓问题会快很多。