Python PIL库实现中文验证码生成的完整指南

Finn
Finn
发布时间:2026-10-12| 5人浏览过
原创

本文详解使用 Python PIL(Pillow)库编写中文验证码的完整流程。通过配置运行环境、加载系统字体、结合随机坐标与干扰线条绘制技术,快速生成具备基础防爬能力的中文图片验证码。附带优化后的可运行源码及常见报错排查方案。

中文验证码生成目标与核心原理

Web 安全防护中,验证码常用于拦截恶意自动化登录尝试。传统英文验证码容易被 OCR 破解,而随机渲染汉字配合视觉干扰能显著提升识别门槛。其核心在于利用 PIL 库的图像处理能力,将离散的 Unicode/GBK 字符映射到位图画布上,并通过坐标偏移、色彩随机化及几何变换(如旋转、划线)破坏规则的字符排列特征,使机器难以定位提取。

运行环境与前置配置

PIL 官方已停止维护,现代开发统一使用社区分支 Pillow。请确保 Python 版本为 3.x,并通过终端执行以下命令安装依赖:

pip install Pillow

中文渲染依赖系统内置字体文件。Windows 系统通常自带宋体文件 SIMSUN.TTC(位于系统目录),Mac/Linux 用户需提前拷贝至项目同级目录或填写绝对路径。若路径错误,代码抛出 OSError 即为字体未找到。

第1步:实例化画布与字体控制器

所有图像操作均围绕 Image 对象展开。创建透明或纯色背景画布后,调用 ImageFont.truetype 绑定指定字号的字体文件。此步骤决定了最终输出的分辨率与文字轮廓精度。

第2步:封装随机字符生成与抗干扰逻辑

验证码不可预测性来源于随机种子控制。代码通过 RandomChar 类映射 GBK 区位码范围,安全提取常用汉字;ImageChar 类负责计算每个字符的落点坐标(引入间隙变量 gap 防止重叠),并为单字应用微小的随机旋转。同时遍历生成多条带随机颜色的线段(randLine),覆盖于文字下方形成噪点屏障。

第3步:整合绘图指令并保存输出

初始化 ImageChar 实例后,依次触发 randChinese 完成字符布局与干扰层叠加,最后调用 save 将内存中的 RGB 矩阵序列化写入磁盘。以下为完整整合代码(已适配 Python 3 语法规范):

# -*- coding: utf-8 -*-
from PIL import Image, ImageDraw, ImageFont
import random

class RandomChar:
    @staticmethod
    def unicode_char():
        val = random.randint(0x4E00, 0x9FBF)
        return chr(val)

    @staticmethod
    def gb2312_char():
        head = random.randint(0xB0, 0xCF)
        body = random.randint(0xA0, 0xFE)
        return bytes([head, body]).decode('gbk')

class ImageChar:
    def __init__(self, font_color=(0, 0, 0), size=(100, 40), font_path='SIMSUN.TTC', bg_color=(255, 255, 255), font_size=20):
        self.size = size
        self.font_path = font_path
        self.bg_color = bg_color
        self.font_size = font_size
        self.font_color = font_color
        self.font = ImageFont.truetype(self.font_path, self.font_size)
        self.image = Image.new('RGB', size, bg_color)

    def draw_text(self, pos, txt, fill):
        draw = ImageDraw.Draw(self.image)
        draw.text(pos, txt, font=self.font, fill=fill)

    def rand_rgb(self):
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    def rand_point(self):
        w, h = self.size
        return (random.randint(0, w), random.randint(0, h))

    def draw_lines(self, count):
        draw = ImageDraw.Draw(self.image)
        for _ in range(count):
            draw.line([self.rand_point(), self.rand_point()], self.rand_rgb())

    def render_chinese(self, count):
        gap = 5
        start_x = 0
        for i in range(count):
            char = RandomChar().gb2312_char()
            x = start_x + self.font_size * i + random.randint(0, gap) + gap * i
            y = random.randint(-3, 3)
            self.draw_text((x, y), char, self.rand_rgb())
        self.draw_lines(15)

    def save(self, path):
        self.image.save(path)

# 执行生成
ic = ImageChar(font_color=(100, 211, 90))
ic.render_chinese(4)
ic.save('captcha_result.png')
生成的四张随机中文字符验证码示例图
运行脚本后输出的中文验证码效果图

关键注意事项与异常处理

  • 编码兼容性:原稿涉及 Python 2 的 unichr 与十六进制转义解析,现代环境直接运行会报语法错误。上述代码已替换为 chr() 与 bytes().decode() 标准库方法,开箱即用。
  • 旋转边界裁剪:Image.rotate 默认开启 expand=False 时,超出原始画布的像素会被截断。若需保持完整字形,可在旋转时设 expand=True 并重新缩放画布。
  • 字体回退机制:生产环境中建议读取环境变量或提供多种备选字体路径(如 Courier.ttf、arial.ttf),降低跨平台部署时的 OSError 风险。

以上就是 Python PIL库实现中文验证码生成的详细流程,关于更多 Python 图像自动化与前端反爬虫对抗的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。