直接用pytesseract识别验证码基本无效,因其专为清晰印刷体设计,而验证码本质是“人类易读、机器难解”的挑战;真正有效的防刷依赖服务端session绑定校验、前端行为约束与ip级限流。

为什么直接用 pytesseract 识别验证码基本无效
多数人一上来就搜“Python 验证码识别”,装完 pytesseract 加几行 OCR 代码,发现对带干扰线、扭曲字符、低对比度的图片准确率接近 0%。这不是你模型没调好,而是这类验证码根本不是为 OCR 设计的——它本质是“人类易读、机器难解”的挑战,而 pytesseract 默认处理的是清晰印刷体文本。
真正能落地的防刷,不靠“识别难度”,而靠“行为隔离”和“状态约束”。OCR 是对抗思路,成本高、维护重、容易失效;服务端控制才是主干。
Flask + session 实现验证码绑定与校验
核心逻辑:生成验证码时,把答案存进用户 session,并设置过期时间;提交表单时,只比对 session 中的值,不依赖图片内容本身是否可识别。
-
session必须启用且安全(app.secret_key设为随机密钥,禁用SESSION_COOKIE_HTTPONLY=False) - 验证码图片响应头必须加
Cache-Control: no-store,否则浏览器或 CDN 可能缓存旧图,导致用户看到 A 图却要输 B 图的答案 - 校验失败后,应立即清空当前 session 中的
captcha_code,防止重放
示例关键片段:
from flask import Flask, session, request, jsonify
import random
import string
<p>app = Flask(<strong>name</strong>)
app.secret_key = 'your-secret-key-here' # 生产环境用 secrets.token_hex()</p><p>@app.route('/captcha')
def get_captcha():
code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
session['captcha_code'] = code
session.permanent = True</p><h1>此处返回图片二进制流(如用 PIL 绘制),略</h1><pre class="brush:python;toolbar:false;">return send_file(...)@app.route('/login', methods=['POST']) def login(): user_input = request.form.get('captcha') stored = session.pop('captcha_code', None) # 一次性消费 if not stored or user_input != stored: return jsonify({'error': '验证码错误'}), 400
继续登录逻辑...
前端必须禁用自动填充和粘贴绕过
很多“防刷”失效,是因为用户用 Ctrl+V 粘贴之前截屏识别出的验证码,或者浏览器自动填充历史值。这会让服务端校验形同虚设。
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
- 输入框加
autocomplete="off"和autocapitalize="off" - 监听
paste事件并event.preventDefault()(注意:需配合用户提示,否则体验差) - 添加
oninput限制长度为 4,且只接受大小写字母和数字:value.replace(/[^A-Za-z0-9]/g, '').slice(0,4) - 验证码图片点击刷新时,同步清空输入框并 focus
高频请求直接拦截,别等验证码环节
真正的攻击者不会老老实实点图片、输文字。他们用脚本批量请求 /captcha 接口,攒几百个 code 后并发提交。这时候验证码只是延时器,不是防火墙。
必须在反向代理(如 Nginx)或网关层做 IP 级限流:
- Nginx 中用
limit_req_zone $binary_remote_addr zone=captcha:10m rate=2r/s控制单 IP 每秒最多 2 次/captcha请求 - 对
/login接口也加更严策略,比如 5 分钟内同一 IP 最多尝试 5 次,超限则返回 429 并要求等 15 分钟 - 若使用 Redis,可用
INCR+EXPIRE实现滑动窗口计数,比固定窗口更抗突发
验证码只是最后一道轻量防线,不是流量过滤器。它的存在意义,是让正常用户几乎无感,但让自动化脚本的成本显著高于收益。
真正麻烦的从来不是“怎么画歪一点字符”,而是“怎么让同一个 IP 在 1 秒内既不能刷图又不能爆破又不能伪造 session”。这些点漏掉任意一个,图形验证码就只剩心理安慰作用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










