本文目录导读:

- 核心思路
- 环境准备
- 方法一:传统图像处理 + Tesseract OCR(最简方案)
- 方法二:使用深度学习框架(PaddleOCR/DBNet + SVTR)
- 方法三:训练自定义深度学习模型(高阶方案)
- 方法四:第三方打码平台(工程化最优方案)
- 总结:如何选择?
- 重要提醒:法律与道德
识别图形验证码(CAPTCHA)是一个典型的计算机视觉与模式识别问题,脚本实现这一功能通常依赖于OCR(光学字符识别)、图像预处理以及近年来主流的深度学习。
根据验证码的复杂程度(从简单的数字字母到复杂的扭曲、粘连、背景干扰),识别的技术路线也不同,以下是几种主流的实现方式和脚本示例。
核心思路
- 获取图像:下载或截图验证码图片。
- 图像预处理:去除背景噪点、灰度化、二值化、分割字符。
- 识别:将处理后的图像转换为文本。
- 传统方法:使用 OCR 库(如 Tesserocr)。
- 机器学习方法:使用深度学习模型(如 CNN + RNN + CTC)。
- 返回结果:输出识别出的文本字符串。
环境准备
建议使用 Python 环境,需要安装以下库:
# 基础库 pip install requests pillow opencv-python # OCR 方法(适用于简单验证码) pip install pytesseract # 还需要安装 Tesseract-OCR 引擎:https://github.com/tesseract-ocr/tesseract # 深度学习端到端方法(适用于复杂验证码) pip install torch torchvision torchaudio pip install paddleocr # 或使用 PaddleOCR
传统图像处理 + Tesseract OCR(最简方案)
适用场景:背景干净、字符无严重扭曲、未粘连的简单字母数字验证码。
import cv2
import requests
import pytesseract
from PIL import Image
import numpy as np
def clean_image(image_path):
"""图像预处理:去噪、二值化"""
# 读取图片
img = cv2.imread(image_path)
# 转为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波去噪
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
# 二值化(阈值分割)
_, binary = cv2.threshold(blurred, 150, 255, cv2.THRESH_BINARY_INV)
return binary
def recognize_by_ocr(image_path):
"""使用 Tesseract 识别"""
processed_img = clean_image(image_path)
# 配置参数:PSM 8 表示单字符识别,--oem 1 表示 LSTM 引擎
config = r'--oem 3 --psm 7 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
text = pytesseract.image_to_string(processed_img, config=config, lang='eng')
# 去除空格和换行
return text.strip().replace('\n', '').replace(' ', '')
# 使用示例
result = recognize_by_ocr('captcha.png')
print(f"识别结果: {result}")
优点:代码简单,无需训练模型。 缺点:对扭曲、粘连、噪点多的验证码准确率很低(< 30%)。
使用深度学习框架(PaddleOCR/DBNet + SVTR)
适用场景:大多数常见的复杂验证码,如:字符旋转、粘连、加噪、线条干扰。
PaddleOCR 是百度开源的 OCR 工具包,内置了专门针对验证码的识别模型。
from paddleocr import PaddleOCR
import cv2
# 初始化 OCR
# 使用检测+识别模型,加载预训练参数
ocr = PaddleOCR(
use_angle_cls=True, # 启用文本方向分类
lang='en', # 英文模型
det_db_thresh=0.3, # 检测阈值(调低可应对较淡的字符)
rec_char_dict_path=None, # 使用默认字典(0-9 A-Z)
use_gpu=False # 如果显卡不够,建议 False
)
def recognize_by_paddle(image_path):
"""使用 PaddleOCR 识别验证码"""
result = ocr.ocr(image_path, cls=True)
code = ''
if result[0] is not None:
# 提取识别文本
for line in result[0]:
code += line[1][0] # line[1][0] 是识别字符串
return code
# 使用示例
result = recognize_by_paddle('complex_captcha.png')
print(f"识别结果: {result}")
优点:开箱即用,准确率较高(约 70%-90%),适应性强。 缺点:首次运行需下载模型(约 100MB),推理速度比 Tesseract 慢(约 0.5-1秒/张)。
训练自定义深度学习模型(高阶方案)
适用场景:特定网站的高强度验证码(如极验滑动验证码除外),批量自动化需要高准确率(>95%)。
常见架构:CNN(特征提取) + RNN/Transformer(序列建模) + CTC Loss(无需对齐)
# 伪代码展示流程,此处省略具体网络实现
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from PIL import Image
class CaptchaModel(nn.Module):
"""简单的 CNN+BiLSTM+CTC 模型"""
# ... (具体的层定义)
def predict_captcha(model, image_path, char_dict):
"""
推理步骤:
1. 加载图片,缩放到固定尺寸 (e.g., 100x40)
2. 转为 Tensor -> 模型前向传播 -> 输出概率矩阵
3. 使用贪心解码或 Beam Search 获得字符索引序列
4. 将索引映射回字符
"""
# 模型加载 & 预处理
image = Image.open(image_path).convert('L')
transform = transforms.Compose([
transforms.Resize((40, 100)), # (h, w)
transforms.ToTensor(),
transforms.Normalize([0.5], [0.5])
])
x = transform(image).unsqueeze(0) # batch dim
with torch.no_grad():
logits = model(x) # [seq_len, batch, num_classes]
# 取 argmax 得到预测索引序列
pred_indices = logits.argmax(dim=-1).squeeze()
# 去重 (CTC 解码) 并映射为字符
code = ''.join([char_dict[i] for i in pred_indices if i != 0]) # 0 为 blank
return code
数据准备:你需要收集大量(至少几千张)该网站的验证码并人工标注。 训练耗时:GPU 训练需 2-10 小时。
第三方打码平台(工程化最优方案)
适用场景:生产环境,需要极高成功率(>99%),但不想投入研发训练模型。
通过 HTTP 接口将验证码图片发给人工打码平台(如 2Captcha、打码兔、AI开放平台的 Captcha 识别服务)。
import requests
import base64
def recognize_by_api(image_path, api_key='YOUR_KEY'):
"""调用第三方打码平台"""
with open(image_path, 'rb') as f:
img_base64 = base64.b64encode(f.read()).decode()
# 以超级鹰为例
url = 'http://upload.chaojiying.com/upload/Processing'
data = {
'user': 'your_username',
'pass': 'your_password',
'softid': 'your_softid',
'codetype': 1902 # 常见验证码类型代码
}
files = {'userfile': ('captcha.jpg', img_base64, 'image/jpeg')}
resp = requests.post(url, data=data, files=files)
return resp.json().get('pic_str')
# 使用示例
result = recognize_by_api('hard_captcha.png')
print(f"打码结果: {result}")
优点:识别率极高,无需维护模型,稳定性好。 缺点:有费用(每次约 0.01~0.05元),且有延迟(人工打码通常 1~5秒)。
如何选择?
| 验证码类型 | 推荐方案 | 预期准确率 | 成本 |
|---|---|---|---|
| 简单数字/字母,无扭曲 | Tesseract + 预处理 | 60%-80% | 免费 |
| 中等复杂(线条干扰、轻微扭曲) | PaddleOCR (SVTR) | 80%-95% | 免费 |
| 高度扭曲、粘连、有字符阴影 | PaddleOCR + 针对性后处理 | 70%-90% | 免费 |
| 特定网站、批量、要求极高成功率 | 第三方打码平台 | 99%+ | 按次收费 |
| 长期、大规模且预算有限 | 自训练 CNN+CTC 模型 | 95%+ | 免费+算力 |
重要提醒:法律与道德
- 遵守 Robots 协议:识别验证码通常用于自动化爬虫,请确保你有权访问目标网站的数据。
- 不用于攻击:不要使用验证码识别技术去攻击银行、政府、邮箱等安全系统的验证码,这可能构成非法获取计算机信息系统数据罪。
- 不用于滥用:不要利用此技术进行刷票、抢票、黄牛等影响正常商业秩序的行为。