Python案例:如何生成随机验证码?从基础到高级实现全解析
目录导读
- 验证码的作用与常见类型
- 基础实现:随机数字/字母验证码
- 进阶实现:带干扰元素的图形验证码
- 实战案例:生成4位纯数字验证码
- 实战案例:生成6位混合字符验证码
- 高级应用:调用PIL库创建图片验证码
- 常见问题与解答(QA)
- 最后总结与SEO优化建议
验证码的作用与常见类型
在Web开发、用户注册、登录验证等场景中,验证码是防止恶意机器人自动提交表单的经典手段,常见的验证码类型包括:

- 纯数字验证码(如:
3482) - 字母数字混合验证码(如:
A7f2X) - 算数运算验证码(如:
12+5=?) - 图形验证码(带扭曲、干扰线、噪点)
本文将以Python语言为核心,详解从最简单到相对复杂的验证码生成实现,覆盖random、string、PIL(Pillow)等常用库。
基础实现:随机数字/字母验证码
最基础的验证码只需从数字或字母集合中随机抽取若干字符,Python内置的random模块与string模块可以轻松完成。
核心思路:
- 定义字符池:
string.digits(数字)、string.ascii_letters(大小写字母) - 使用
random.choices(pool, k=length)生成列表 - 用
join()拼接成字符串
进阶实现:带干扰元素的图形验证码
为了让验证码更难被程序识别,通常需要添加:
- 随机背景色/字体色
- 干扰线(随机位置、颜色、弧度)
- 噪点
- 字体扭曲或旋转
这需要借助第三方库Pillow(PIL的现代分支),安装命令:pip install pillow
实战案例:生成4位纯数字验证码
import random
import string
def gen_digit_code(length=4):
pool = string.digits
code = ''.join(random.choices(pool, k=length))
return code
print(gen_digit_code()) # 8231
代码解析:
string.digits含'0123456789'random.choices允许重复抽取,适合验证码场景- 该函数默认生成4位数字,可修改
length参数
实战案例:生成6位混合字符验证码
import random
import string
def gen_mixed_code(length=6):
pool = string.digits + string.ascii_uppercase
# 避免混淆,可手动排除 O、0、I、1
pool = pool.replace('O', '').replace('0', '').replace('I', '').replace('1', '')
code = ''.join(random.choices(pool, k=length))
return code
print(gen_mixed_code()) # A7X2F9
注意点:
- 实际应用中常去除易混淆字符(如
O与0,I与1) - 全大写或混合大小写均可,但通常建议统一为大写以提高可读性
高级应用:调用PIL库创建图片验证码
from PIL import Image, ImageDraw, ImageFont
import random
import string
def create_image_captcha(text=None, width=160, height=60):
if text is None:
text = ''.join(random.choices(string.digits, k=4))
# 创建画布
img = Image.new('RGB', (width, height), color=(255, 255, 255))
draw = ImageDraw.Draw(img)
# 设置字体(需确保字体文件存在,可用系统字体或下载)
try:
font = ImageFont.truetype("arial.ttf", 40)
except:
font = ImageFont.load_default()
# 绘制文字,并加入随机偏移
for i, char in enumerate(text):
x = i * (width // len(text)) + random.randint(0, 10)
y = random.randint(0, 15)
draw.text((x, y), char, fill=(0, 0, 0), font=font)
# 添加干扰线
for _ in range(3):
start = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([start, end], fill=(random.randint(0, 200), random.randint(0, 200), random.randint(0, 200)), width=2)
# 添加噪点
for _ in range(200):
xy = (random.randint(0, width), random.randint(0, height))
draw.point(xy, fill=(random.randint(0, 200), random.randint(0, 200), random.randint(0, 200)))
img.show() # 或保存:img.save('captcha.png')
return img
create_image_captcha()
关键点说明:
ImageFont.truetype需要字体文件路径;若无可用系统字体,可用load_default()- 每个字符加入
random.randint使位置偏移,避免整齐排列 - 干扰线使用
draw.line,噪点使用draw.point,颜色随机
常见问题与解答(QA)
Q1:如何确保验证码每次都不重复?
A:Python的random.choices已基于随机种子生成序列,默认每调用一次都不同,若需更严格唯一性,可结合时间戳或UUID作为种子。
Q2:生成的图片验证码内存消耗大怎么办?
A:若需高并发生成,建议设置图片尺寸较小(如120x40),并使用img.save(fp, format='JPEG')压缩,或直接返回字节流(BytesIO)。
Q3:如何让验证码更难被OCR识别?
A:在PIL中增加字体旋转(draw.text不支持直接旋转,需先创建文字图层再旋转)、使用艺术字体、增加背景纹理、使用波浪形干扰线。
Q4:可以生成中文验证码吗?
A:可以,将字符池改为中文列表(如 ['你','好','世','界']),并确保使用支持中文的字体文件(如msyh.ttf)。
Q5:验证码需要存服务器吗?
A:需要,生成时同时将验证码文本存到Session或Redis中,用户提交时比对,切勿仅依赖前端或cookie存储。
最后总结与SEO优化建议
本文核心收获:
- 掌握用
random+string生成纯数字/混合字符验证码 - 学会使用
Pillow库创建带干扰元素的图形验证码 - 理解验证码在防刷场景中的核心设计与安全性考量
搜索引擎优化要点:
- 关键词自然融入:
Python生成随机验证码、图片验证码Python、PIL验证码、H2、首段重复出现 - 代码块格式清晰,便于搜索引擎提取示例
- 提供问答环节,符合用户搜索行为(常有人搜索“验证码不重复怎么办”)
- 无外部链接、无广告,符合Google EEAT要求
如果你正在开发登录注册模块、API防护或爬虫防屏蔽,这几种验证码生成方案足够覆盖90%的常见需求,建议根据业务场景选择合适复杂度:简单防刷用纯数字,中等安全用混合字符+图片,高强度用算数或行为验证。
延伸阅读:Python结合captcha库(国产)可一键生成验证码;考虑集成Google reCAPTCHA实现人机验证。