php无法内置识别验证码,需依赖tesseract ocr或打码平台;关键在图像预处理、base64正确编码、codetype精准选择及识别结果校验。

验证码识别不是“破解”,而是图像预处理 + OCR 或打码平台调用
直接说结论:PHP 本身没有内置的验证码识别能力,所谓“破”其实是绕过或替代——要么用第三方 OCR(如 Tesseract),要么对接打码平台(如超级鹰、云打码、若快)。真正难的不是调用接口,而是图像质量差导致识别率低,或者验证码带干扰线/扭曲/粘连时,OCR 基本失效。
多数人卡在第一步:传过去的图片服务器返回 ERROR_IMAGE_EMPTY 或 UNICODE_ERROR,其实只是没做 base64 编码或没去掉 data URL 前缀。
- 务必先用
file_get_contents()或curl拿到原始二进制图片数据,不要传 URL 字符串给打码平台 - 若验证码图是 base64 data URL(如
data:image/png;base64,xxx),必须用preg_replace()去掉前缀再base64_decode() - 打码平台返回的识别结果是纯文本,不带空格/换行,但有些验证码本身含空格(如“AB 2C”),平台可能返回“AB2C”——得靠你业务逻辑补全或校验
调用超级鹰 API 时,upload 接口必须传对 codetype 和 timeout
超级鹰的 upload 接口(http://upload.chaojiying.net/Upload/Processing.php)不是万能的,codetype 决定识别策略。填错就等于让 OCR “瞎猜”:
-
codetype=1004:英文+数字(无干扰线,常见于登录页) -
codetype=1005:中文+英文+数字(需付费,且对字体要求高) -
codetype=2004:坐标验证码(点击图中文字,返回 x,y 坐标) -
timeout=60是最大等待秒数,设太小(如 10)容易返回UNKNOWN_ERROR,设太大影响响应速度
示例关键片段:
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'user' => 'your_user',
'pass' => 'your_pass',
'softid' => 'your_softid',
'codetype' => '1004',
'file_base64' => base64_encode($img_binary),
]);
用 Tesseract 在 PHP 中做本地 OCR,tesseract 命令和图像预处理缺一不可
想离线识别?可以,但别指望直接 exec('tesseract xxx.png stdout') 就出结果。Tesseract 对输入极其敏感:
- 必须先用 ImageMagick 或 GD 处理:灰度化 → 二值化(
threshold值通常 127–180)→ 去噪点(median-filter)→ 放大 2–3 倍(提高小字体识别率) -
tesseract调用要加-c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyz,否则默认识别所有 Unicode,易把“0”认成“O”或“o” - PHP 的
exec()可能被禁用(disable_functions),此时只能走 REST 封装的 Tesseract 服务(如 tesseract-server),而非本地命令
打码平台返回 result 后,一定要做二次校验,不能直接提交
打码平台平均识别率在 85%–95%,但“识别成功”不等于“正确”。尤其当验证码用于登录或支付场景,一次失败可能触发风控锁账号。
- 拿到
result后,先检查长度是否符合预期(如固定 4 位,就 reject 长度 ≠ 4 的结果) - 用正则过滤非法字符:
preg_match('/^[a-zA-Z0-9]{4}$/', $result),拒绝含中文、符号、空格的结果 - 如果业务允许,可对同一张图重试 2–3 次(换
codetype或换平台),取多数结果,比单次更稳
最常被忽略的一点:打码平台的 error_code 是字符串,不是整数。比如 "9999" 表示余额不足,但有人用 == 9999 判断,永远不成立。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











