本文目录导读:

我来介绍几种在Python中生成验证码图片的方法:
方法1:使用 captcha 库(最简单)
# 首先安装:pip install captcha
from captcha.image import ImageCaptcha
import random
import string
def generate_captcha_captcha():
"""使用captcha库生成验证码"""
# 创建ImageCaptcha对象
image = ImageCaptcha(width=200, height=80, fonts=['Arial.ttf'])
# 生成随机验证码(4位数字+字母组合)
captcha_text = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
# 生成图片
image.write(captcha_text, 'captcha_simple.png')
# 或者直接获取图片数据
data = image.generate(captcha_text)
print(f"验证码文字: {captcha_text}")
return captcha_text
# 使用示例
generate_captcha_captcha()
方法2:使用 Pillow 库自定义(推荐)
# 首先安装:pip install Pillow
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
import string
class CaptchaGenerator:
def __init__(self, width=200, height=80):
self.width = width
self.height = height
self.font_size = 40
def generate_random_color(self, min_val=50, max_val=200):
"""生成随机颜色"""
return (random.randint(min_val, max_val),
random.randint(min_val, max_val),
random.randint(min_val, max_val))
def generate_text(self, length=4):
"""生成随机验证码文本"""
chars = string.ascii_uppercase + string.digits
return ''.join(random.choice(chars) for _ in range(length))
def create_captcha_image(self, text=None):
"""创建验证码图片"""
if text is None:
text = self.generate_text()
# 创建空白图片
image = Image.new('RGB', (self.width, self.height),
self.generate_random_color(200, 255))
draw = ImageDraw.Draw(image)
# 加载字体(如果没有中文字体,使用默认字体)
try:
font = ImageFont.truetype("arial.ttf", self.font_size)
except:
font = ImageFont.load_default()
# 绘制验证码文字
for i, char in enumerate(text):
# 随机旋转角度
angle = random.randint(-30, 30)
# 创建单个字符的图片
char_image = Image.new('RGBA', (self.font_size, self.font_size), (0, 0, 0, 0))
char_draw = ImageDraw.Draw(char_image)
char_draw.text((0, 0), char, font=font,
fill=self.generate_random_color(0, 100))
# 旋转字符
rotated_char = char_image.rotate(angle, expand=1)
# 计算位置
x = 20 + i * 45
y = 10 + random.randint(-5, 10)
# 粘贴到主图片
image.paste(rotated_char, (x, y), rotated_char)
# 添加随机噪点
for _ in range(5):
if random.random() > 0.5:
noise_color = self.generate_random_color(150, 255)
draw.line([
(random.randint(0, self.width), random.randint(0, self.height)),
(random.randint(0, self.width), random.randint(0, self.height))
], fill=noise_color, width=2)
# 添加干扰线
for _ in range(3):
line_color = self.generate_random_color(100, 200)
start_point = (random.randint(0, self.width), random.randint(0, self.height))
end_point = (random.randint(0, self.width), random.randint(0, self.height))
draw.line([start_point, end_point], fill=line_color, width=2)
# 添加滤镜增加难度
image = image.filter(ImageFilter.SMOOTH_MORE)
return image, text
def save_captcha(self, filename="captcha.png"):
"""生成并保存验证码"""
image, text = self.create_captcha_image()
image.save(filename)
print(f"验证码已保存到: {filename}")
print(f"验证码文字: {text}")
return text
# 使用示例
generator = CaptchaGenerator()
text = generator.save_captcha("my_captcha.png")
方法3:交互式验证码生成器
import tkinter as tk
from PIL import Image, ImageTk, ImageDraw, ImageFont
import random
import string
class CaptchaApp:
def __init__(self):
self.root = tk.Tk()
self.root.title("验证码生成器")
self.root.geometry("400x300")
self.captcha_text = ""
self.setup_ui()
self.generate_new_captcha()
def setup_ui(self):
# 显示验证码的标签
self.captcha_label = tk.Label(self.root)
self.captcha_label.pack(pady=20)
# 输入框
self.entry = tk.Entry(self.root, font=("Arial", 14))
self.entry.pack(pady=10)
# 按钮
btn_frame = tk.Frame(self.root)
btn_frame.pack(pady=10)
tk.Button(btn_frame, text="刷新验证码",
command=self.generate_new_captcha).pack(side=tk.LEFT, padx=5)
tk.Button(btn_frame, text="验证",
command=self.verify_captcha).pack(side=tk.LEFT, padx=5)
# 结果显示
self.result_label = tk.Label(self.root, text="", font=("Arial", 12))
self.result_label.pack(pady=10)
def generate_captcha(self):
"""生成验证码图片"""
width, height = 200, 80
image = Image.new('RGB', (width, height), (240, 240, 240))
draw = ImageDraw.Draw(image)
# 生成随机文本
chars = string.ascii_uppercase + string.digits
self.captcha_text = ''.join(random.choice(chars) for _ in range(4))
# 尝试加载字体
try:
font = ImageFont.truetype("arial.ttf", 40)
except:
font = ImageFont.load_default()
# 绘制文字
for i, char in enumerate(self.captcha_text):
x = 20 + i * 45
y = 10 + random.randint(-5, 10)
color = (random.randint(0, 100),
random.randint(0, 100),
random.randint(0, 100))
draw.text((x, y), char, font=font, fill=color)
# 添加干扰线
for _ in range(3):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line([(x1, y1), (x2, y2)],
fill=(random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255)),
width=2)
return image
def generate_new_captcha(self):
"""生成新的验证码"""
image = self.generate_captcha()
photo = ImageTk.PhotoImage(image)
self.captcha_label.config(image=photo)
self.captcha_label.image = photo
self.entry.delete(0, tk.END)
self.result_label.config(text="")
def verify_captcha(self):
"""验证输入"""
user_input = self.entry.get().upper()
if user_input == self.captcha_text:
self.result_label.config(text="✓ 验证成功!", fg="green")
else:
self.result_label.config(text="✗ 验证失败,请重试", fg="red")
def run(self):
self.root.mainloop()
# 使用示例
app = CaptchaApp()
app.run()
方法4:将验证码保存为字节流(用于Web应用)
from PIL import Image, ImageDraw, ImageFont
import random
import string
import io
def generate_captcha_bytes():
"""生成验证码并返回字节流"""
width, height = 200, 80
# 创建图片
image = Image.new('RGB', (width, height), (255, 255, 255))
draw = ImageDraw.Draw(image)
# 生成随机文本
chars = string.ascii_uppercase + string.digits
captcha_text = ''.join(random.choice(chars) for _ in range(4))
# 绘制文字
for i, char in enumerate(captcha_text):
color = (random.randint(0, 100),
random.randint(0, 100),
random.randint(0, 100))
draw.text((20 + i * 45, 20), char, fill=color)
# 保存为字节流
buffer = io.BytesIO()
image.save(buffer, format='PNG')
buffer.seek(0)
return buffer.getvalue(), captcha_text
# 使用示例
image_bytes, text = generate_captcha_bytes()
print(f"验证码文字: {text}")
print(f"图片大小: {len(image_bytes)} 字节")
使用建议
- 简单需求:使用
captcha库,一行代码即可生成 - 自定义样式:使用 Pillow 自定义颜色、字体、干扰线等
- Web应用:生成字节流返回给前端
- 安全性考虑:
- 验证码有效期(建议5分钟内)
- 验证后立即销毁
- 限制验证尝试次数
- 避免使用简单可预测的模式
这些示例涵盖了从简单到复杂的不同场景,你可以根据具体需求选择合适的方法。