Python使用PIL库实现验证码图片生成与Web集成

小石头
小石头
发布时间:2026-10-12 | 3人浏览过
原创

介绍如何利用Python的PIL库编写自定义验证码生成函数,支持字符集、尺寸、字体及干扰元素参数配置。提供将验证码直接保存为文件以及在Django等Web框架中使用StringIO模块在内存中动态输出图片的完整代码示例,并附带字体缺失报错的排查方法。

验证码生成的核心逻辑与参数设计

利用Python进行图形验证码开发的本质是在内存中创建一个画布,随机选取目标长度的字符集合(大小写字母与数字),调用PIL的绘图接口完成渲染。为避免机器识别,通常需叠加干扰线、随机噪点,并施加透视变换与边缘增强滤镜增加OCR提取难度。整个流程可通过封装函数实现参数化控制,便于在不同业务场景中灵活调整安全级别与视觉风格。

第1步:准备开发环境与依赖包

验证码渲染依赖第三方图像处理库。执行以下命令安装或升级至支持现代Python环境的版本:

  1. 打开终端或命令行工具
  2. 运行 pip install Pillow 获取最新官方镜像
  3. 验证导入无报错:from PIL import Image, ImageDraw, ImageFont, ImageFilter

确认环境就绪后,可创建主脚本文件引入核心生成逻辑。

第2步:编写带参数的验证码生成函数

以下为经过兼容性优化的核心代码。已修正原示例中的老旧语法,并完善中文注释说明各入参的作用域与默认值:

# coding=utf-8
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

_letter_cases = "abcdefghjkmnpqrstuvwxy"  
_upper_cases = _letter_cases.upper() 
_numbers = ''.join(map(str, range(3, 10))) 
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))

def create_validate_code(size=(120, 30),
             chars=init_chars,
             img_type="GIF",
             mode="RGB",
             bg_color=(255, 255, 255),
             fg_color=(0, 0, 255),
             font_size=18,
             font_type="ae_AlArabiya.ttf",
             length=4,
             draw_lines=True,
             n_line=(1, 2),
             draw_points=True,
             point_chance=2):
  width, height = size 
  img = Image.new(mode, size, bg_color)
  draw = ImageDraw.Draw(img)

  def get_chars():
    return random.sample(chars, length)

  def create_lines():
    line_num = random.randint(*n_line)
    for i in range(line_num):
      begin = (random.randint(0, size[0]), random.randint(0, size[1]))
      end = (random.randint(0, size[0]), random.randint(0, size[1]))
      draw.line([begin, end], fill=(0, 0, 0))

  def create_points():
    chance = min(100, max(0, int(point_chance)))
    for w in range(width):
      for h in range(height):
        tmp = random.randint(0, 100)
        if tmp > 100 - chance:
          draw.point((w, h), fill=(0, 0, 0))

  def create_strs():
    c_chars = get_chars()
    strs = ' %s ' % ' '.join(c_chars)
    font = ImageFont.truetype(font_type, font_size)
    font_width, font_height = font.getsize(strs)
    draw.text(((width - font_width) / 3, (height - font_height) / 3),
              strs, font=font, fill=fg_color)
    return ''.join(c_chars)

  if draw_lines:
    create_lines()
  if draw_points:
    create_points()
  strs = create_strs()

  params = [1 - float(random.randint(1, 2)) / 100,
       0, 0, 0,
       1 - float(random.randint(1, 10)) / 100,
       float(random.randint(1, 2)) / 500,
       0.001,
       float(random.randint(1, 2)) / 500]
  img = img.transform(size, Image.PERSPECTIVE, params)
  img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
  return img, strs

第3步:本地调试保存图片并观察效果

初次接入时可直接在脚本末尾添加运行入口,将返回的Image对象写入磁盘进行视觉核对。完成后会生成一张GIF格式的静态帧图片:

if __name__ == "__main__":
  code_img = create_validate_code()
  code_img.save("validate.gif", "GIF")

生成的验证码图片效果:

PIL库生成的含干扰线与噪点的字母数字组合验证码截图
包含随机扭曲与边界增强滤镜处理的GIF格式验证码预览

第4步:在Django中通过内存流动态输出

生产环境中频繁读写磁盘会导致性能瓶颈。Python内置的 StringIO 模块提供类文件接口的内存缓冲区,配合 img.save() 可实现零I/O的HTTP响应流式传输。

Django路由配置(以现代路径写法为例):

# urls.py
from django.urls import path
from . import views
urlpatterns = [
    path('validate/', views.validate, name='validate'),
]

视图层处理逻辑:

# views.py
from django.shortcuts import HttpResponse
try:
    from cStringIO import StringIO
except ImportError:
    from io import StringIO
from validate import create_validate_code

def validate(request):
    mstream = StringIO()
    validate_code = create_validate_code()
    img = validate_code[0]
    img.save(mstream, "GIF")
    request.session['validate'] = validate_code[1]
    return HttpResponse(mstream.getvalue(), "image/gif")

上述操作将正确的校验码存入当前会话,前端表单提交后只需比对 request.POST['captcha_input'] 与 request.session.get('validate') 即可判定合法性。调用方通过 mstream.getvalue() 可直接获取字节流数据。

常见问题排查:字体加载失败的应对策略

执行 ImageFont.truetype() 时若抛出 IOError 或 FileNotFoundError,根本原因是宿主机系统未预装代码中指定的字形文件。解决方法如下:

  1. 登录服务器或开发机,检查指定路径下是否存在 .ttf 后缀的有效字体
  2. 若无对应文件,可从操作系统字体库复制通用字体(如 Windows 的 Arial.ttf,Linux 的 DejaVuSans.ttf)替换传入路径
  3. 修改参数后重新运行,确保控制台无回溯堆栈且能正常返回 Image 实例

以上就是基于Python的PIL库实现验证码图片生成与Django部署的详细内容,更多关于Python图像处理与Web后端开发资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表