配方:绕过简单验证码

配方:绕过简单验证码

配方信息

项目说明
难度⭐⭐ (初级)
预计时间30-45 分钟
所需工具Python 3.7+, Tesseract OCR
适用场景识别简单的图形验证码
前置知识Python 基础, PIL/Pillow 库

📚 前置知识

在开始本配方之前,建议先掌握以下内容:

知识领域重要程度参考资料
Python 基础语法必需了解函数、循环、条件语句等基本概念
HTTP 请求基础必需HTTP/HTTPS 协议
PIL/Pillow 图像处理推荐Python 图像处理库,用于验证码预处理
Chrome DevTools推荐浏览器开发者工具

💡 新手提示: 本配方侧重于简单验证码的识别。对于复杂验证码(滑块、点选等),请参考进阶配方 验证码绕过


你将学到

完成这个配方后,你将能够:

  • ✅ 分析验证码生成和验证流程
  • ✅ 抓取验证码图片
  • ✅ 使用 OCR 技术识别文字
  • ✅ 图像预处理提高识别率
  • ✅ 自动化验证码识别流程
  • ✅ 判断何时应该使用人工打码平台

准备工作

安装依赖

1. 安装 Python 库

1
pip install pillow requests pytesseract opencv-python

2. 安装 Tesseract OCR

Windows:

1
2
3
4
5
# 下载安装包
https://github.com/UB-Mannheim/tesseract/wiki

# 安装后配置环境变量
set PATH=%PATH%;C:\Program Files\Tesseract-OCR

macOS:

1
brew install tesseract

Linux:

1
2
sudo apt-get install tesseract-ocr
sudo apt-get install libtesseract-dev

3. 验证安装

1
2
tesseract --version
# 输出: tesseract 5.x.x

检查清单

  • ☐ 已安装 Python 3.7+
  • ☐ 已安装所有依赖库
  • ☐ Tesseract OCR 正常工作
  • ☐ 了解基本的 Python 和 HTTP 请求

步骤详解

Step 1: 分析验证码流程

1.1 观察验证码

打开一个有验证码的登录页面(或使用下面的示例):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<title>验证码登录</title>
</head>
<body>
<h2>登录</h2>
<input id="username" placeholder="用户名" />
<input id="password" type="password" placeholder="密码" />
<br /><br />
<img
id="captcha"
src="/captcha"
onclick="this.src='/captcha?'+Date.now()"
/>
<br />
<input id="captcha_code" placeholder="验证码" />
<button onclick="login()">登录</button>

<script>
function login() {
const data = {
username: document.getElementById("username").value,
password: document.getElementById("password").value,
captcha: document.getElementById("captcha_code").value,
};

fetch("/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then((r) => r.json())
.then((result) => alert(result.message));
}
</script>
</body>
</html>

1.2 理解验证流程

  1. 获取验证码: GET /captcha → 返回图片
  2. 用户输入: 人工识别并输入
  3. 提交验证: POST /api/login 带上验证码
  4. 服务器验证: 比对答案,返回结果

关键点:

  • 验证码图片 URL: /captcha
  • 验证码需要和登录请求一起提交
  • 通常有会话(Cookie)关联验证码和答案

Step 2: 抓取验证码图片

2.1 编写抓取脚本

创建 captcha_download.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import requests
from PIL import Image
from io import BytesIO

# 创建会话(保持 Cookie)
session = requests.Session()

def download_captcha(url, save_path='captcha.png'):
"""下载验证码图片"""
response = session.get(url)

if response.status_code == 200:
# 保存图片
with open(save_path, 'wb') as f:
f.write(response.content)

# 显示图片
img = Image.open(BytesIO(response.content))
img.show()

print(f"✅ 验证码已保存到: {save_path}")
return True
else:
print(f"❌ 下载失败: {response.status_code}")
return False

if __name__ == '__main__':
url = 'https://example.com/captcha'
download_captcha(url)

2.2 运行测试

1
python captcha_download.py

输出: 图片会自动打开,并保存为 captcha.png


Step 3: OCR 识别验证码

3.1 基础识别

创建 captcha_ocr.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pytesseract
from PIL import Image

def recognize_captcha(image_path):
"""识别验证码"""
# 加载图片
img = Image.open(image_path)

# OCR 识别
text = pytesseract.image_to_string(img, config='--psm 7 digits')

# 清理结果(去除空格和换行)
result = text.strip().replace(' ', '').replace('\n', '')

print(f"识别结果: {result}")
return result

if __name__ == '__main__':
result = recognize_captcha('captcha.png')
print(f"✅ 验证码是: {result}")

参数说明:

  • --psm 7: Page Segmentation Mode = 7(单行文本)
  • digits: 只识别数字

3.2 测试识别

1
python captcha_ocr.py

可能的问题: 识别率很低或完全识别不出来

原因: 验证码有干扰(噪点、线条、倾斜等)


Step 4: 图像预处理

4.1 增强识别率

创建 captcha_preprocess.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import cv2
import numpy as np
from PIL import Image
import pytesseract

def preprocess_image(image_path):
"""预处理验证码图片"""
# 读取图片
img = cv2.imread(image_path)

# 1. 转灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 2. 二值化(去除噪点)
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 3. 去噪(形态学操作)
kernel = np.ones((2, 2), np.uint8)
opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=1)

# 4. 保存处理后的图片
processed_path = 'captcha_processed.png'
cv2.imwrite(processed_path, opening)

print(f"✅ 预处理完成: {processed_path}")
return processed_path

def recognize_with_preprocess(image_path):
"""预处理后识别"""
# 预处理
processed_path = preprocess_image(image_path)

# OCR 识别
img = Image.open(processed_path)
text = pytesseract.image_to_string(img, config='--psm 7 digits')
result = text.strip().replace(' ', '').replace('\n', '')

print(f"识别结果: {result}")
return result

if __name__ == '__main__':
result = recognize_with_preprocess('captcha.png')
print(f"✅ 验证码是: {result}")

4.2 对比效果

1
2
3
4
5
6
7
# 原始识别
python captcha_ocr.py
# 输出: 12O4 (错误)

# 预处理后识别
python captcha_preprocess.py
# 输出: 1234 (正确)

Step 5: 完整自动化流程

5.1 集成所有步骤

创建 auto_login.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import requests
import pytesseract
from PIL import Image
from io import BytesIO
import cv2
import numpy as np

class CaptchaBypass:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()

def download_captcha(self):
"""下载验证码"""
url = f"{self.base_url}/captcha"
response = self.session.get(url)

if response.status_code == 200:
return response.content
return None

def preprocess_image(self, image_bytes):
"""预处理图片"""
# 字节 → numpy array
nparr = np.frombuffer(image_bytes, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 去噪
kernel = np.ones((2, 2), np.uint8)
opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=1)

# numpy array → PIL Image
img_pil = Image.fromarray(opening)
return img_pil

def recognize_captcha(self, img):
"""OCR 识别"""
text = pytesseract.image_to_string(img, config='--psm 7 digits')
result = text.strip().replace(' ', '').replace('\n', '')
return result

def login(self, username, password):
"""自动登录"""
# 1. 下载验证码
print(" 下载验证码...")
captcha_bytes = self.download_captcha()

# 2. 预处理
print(" 预处理图片...")
processed_img = self.preprocess_image(captcha_bytes)

# 3. 识别
print(" 识别验证码...")
captcha_code = self.recognize_captcha(processed_img)
print(f"✅ 识别结果: {captcha_code}")

# 4. 登录
print(" 发送登录请求...")
response = self.session.post(
f"{self.base_url}/api/login",
json={
'username': username,
'password': password,
'captcha': captcha_code
}
)

result = response.json()
print(f" 响应: {result}")

return result

if __name__ == '__main__':
bypass = CaptchaBypass('https://example.com')
result = bypass.login('admin', '123456')

if result['code'] == 0:
print(" 登录成功!")
else:
print(f"❌ 登录失败: {result['message']}")

5.2 运行测试

1
python auto_login.py

预期输出:

1
2
3
4
5
6
7
下载验证码...
预处理图片...
识别验证码...
✅ 识别结果: 1234
发送登录请求...
响应: {'code': 0, 'message': '登录成功', 'token': '...'}
登录成功!

✅ 验证清单

完成后,检查以下项目:

  • ☐ 成功下载验证码图片
  • ☐ Tesseract OCR 能正常识别
  • ☐ 预处理提高了识别率
  • ☐ 完整的自动化流程能运行
  • ☐ 识别准确率达到 60% 以上

进阶练习

练习 1: 提高识别率

尝试不同的预处理方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 方法1: 调整二值化阈值
_, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)

# 方法2: 膨胀和腐蚀
dilate = cv2.dilate(binary, kernel, iterations=1)
erode = cv2.erode(dilate, kernel, iterations=1)

# 方法3: 去除边框
h, w = gray.shape
gray = gray[5:h-5, 5:w-5]

练习 2: 处理字母验证码

修改 OCR 配置:

1
2
3
4
5
# 识别字母+数字
text = pytesseract.image_to_string(img, config='--psm 7')

# 只识别大写字母+数字
text = pytesseract.image_to_string(img, config='--psm 7 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')

练习 3: 使用机器学习

对于复杂验证码,可以使用深度学习:

1
2
3
4
5
6
7
# 使用 CRNN 模型
import torch
from crnn import CRNN

model = CRNN()
model.load_state_dict(torch.load('captcha_model.pth'))
result = model.predict(img)

训练数据: 需要标注 1000+验证码样本


常见问题

Q1: OCR 完全识别不出来怎么办?

A: 可能的原因和解决方案:

  1. 干扰太强:
  • 尝试更激进的预处理
  • 使用机器学习模型
  • 考虑使用打码平台
  1. 字体特殊:
  • 训练 Tesseract 自定义字体
  • 使用深度学习模型
  1. 验证码类型不适合 OCR:
    • 滑块验证码 → 使用轨迹模拟
    • 点选验证码 → 使用图像识别
    • 行为验证码 → 分析行为模式

Q2: 识别率只有 30%,如何提高?

A: 按顺序尝试:

  1. 优化预处理 (可提升到 60%)
  2. 调整 OCR 参数 (可提升到 70%)
  3. 多次识别取最可能结果 (可提升到 80%)
  4. 训练自定义模型 (可提升到 90%+)

代码示例:

1
2
3
4
5
6
7
8
9
# 多次识别
results = []
for i in range(5):
result = recognize_captcha(img)
results.append(result)

# 取出现最多的结果
from collections import Counter
most_common = Counter(results).most_common(1)[0][0]

Q3: 何时应该使用打码平台?

A: 以下情况建议使用打码平台:

  • 验证码非常复杂(扭曲、重叠、背景复杂)
  • 识别率低于 60%且优化无效
  • 验证码类型多变
  • 项目预算充足

推荐平台:

成本: 约 ¥0.001 - ¥0.01 / 张

Q4: 如何处理滑块验证码?

A: 滑块验证码不适合 OCR,需要:

  1. 模拟滑动轨迹:
1
2
3
4
5
6
7
8
9
# 生成模拟人类的轨迹
def generate_track(distance):
track = []
current = 0
while current < distance:
v = random.randint(1, 5)
track.append(v)
current += v
return track
  1. 分析缺口位置:
  • 使用图像识别找到缺口
  • 计算需要移动的距离

参考: 验证码绕过


原理解析

OCR 工作原理

1
图片 → 预处理 → 特征提取 → 字符分类 → 文本输出

关键步骤:

  1. 二值化: 转为黑白图片,突出文字
  2. 去噪: 移除干扰点和线条
  3. 分割: 将字符分割为独立的部分
  4. 识别: 将每个字符与字库对比

为什么需要预处理?

原始验证码的干扰:

  • 噪点(随机点)
  • 干扰线(随机线条)
  • 颜色变化
  • 字符粘连或断裂

预处理可以:

  • 去除噪点和线条
  • 统一颜色(黑白)
  • 修复断裂
  • 分离粘连

相关配方

基础配方

高级配方

工具脚本


恭喜!

你已经掌握了:

  • ✅ 验证码流程分析
  • ✅ OCR 基础使用
  • ✅ 图像预处理技巧
  • ✅ 自动化验证码识别

下一步:


小贴士:

  • OCR 不是万能的,复杂验证码需要机器学习
  • 遵守网站的服务条款和请求频率限制
  • 合法合规使用这些技术

Happy Bypassing!


相关内容

如果这篇文章对你有帮助,请我喝杯咖啡吧~
+5 支付宝支付宝
+5 微信微信