Python生成随机验证码完整教程:从基础到抗干扰实现

小岛来信
小岛来信
发布时间:2026-10-15 | 5人浏览过
原创

本文详细讲解如何利用Python的PIL库生成随机验证码。内容涵盖环境配置、画布与字体设置、字符绘制、以及通过random模块添加噪点和干扰线以提高识别难度。教程包含完整代码示例,演示如何封装函数生成不同颜色和位置的验证码,并支持批量保存至本地,适用于Web开发登录验证及AI模型训练数据准备。

近期在浏览网页时,频繁遇到验证码弹窗,让人不禁怀疑自己是否被大数据标记为机器人。

许多开发者在思考如何用Python绕过验证码机制时感到困惑,

与其被动应对,不如主动出击。今天将逐步指导大家编写验证码生成程序,让他人面对验证码时感到头疼。

准确地说,本文旨在教授如何通过Python代码生成验证码。

1. 环境准备

1. 确保电脑已安装Python 3.4或更高版本。

2. 通过pip安装PIL(Pillow)库。

pip install pillow

3. 默念“人生苦短,我用Python”,随后打开IDLE开始编写代码。

2. 代码实现

1. 确定画布尺寸与背景颜色。

# 导入相关的绘画模块
from PIL import Image, ImageDraw, ImageFont

# 设置背景色
bg_color = (100, 100, 255)

#设置画布长宽(像素)
width = 400
height = 100

# 通过设置生成新的画布
im = Image.new('RGB',(width,height),bg_color)
# 展示画布
im.show()

背景色bg_color采用RGB标准设置,若不喜欢默认颜色,可自行调整。

常见RGB颜色值如下:

运行上述代码后,效果如图所示:

2. 在背景上绘制字符。

首先展示相关代码:

from PIL import Image, ImageDraw, ImageFont


# 省略第一步的代码

# 创建画笔对象
draw = ImageDraw.Draw(im)
# 验证码文本
string = 'MSBC'
# 构造字体对象
font = ImageFont.truetype('./ziti.ttf', 90)
# font = ImageFont.load_default().font
# 构造字体颜色
fontcolor = (255, 100, 100)
# 绘制4个字
draw.text((10, 2), string[0], font=font, fill=fontcolor)
draw.text((110, 2), string[1], font=font, fill=fontcolor)
draw.text((210, 2), string[2], font=font, fill=fontcolor)
draw.text((310, 2), string[3], font=font, fill=fontcolor)


#释放画笔
del draw
#展示图片
im.show()

代码解析如下:

draw = ImageDraw.Draw(im)

在im画布上实例化一个绘图对象(笔)。

font = ImageFont.truetype('./ziti.ttf', 90)
# font = ImageFont.load_default().font

第一个参数用于设置字体,此处使用了下载的.ttf字体文件。若未指定字体文件,可使用默认字体:# font = ImageFont.load_default().font;。

第二个参数设置字体大小,鉴于画布尺寸为400x100,为美观起见,将字体大小设为90x90。

# 构造字体颜色
fontcolor = (255, 100, 100)

字体文本颜色参照第一步中画布的RGB设置。

# 绘制4个字
draw.text((10, 2), string[0], font=font, fill=fontcolor)
draw.text((110, 2), string[1], font=font, fill=fontcolor)
draw.text((210, 2), string[2], font=font, fill=fontcolor)
draw.text((310, 2), string[3], font=font, fill=fontcolor)

draw.text函数用于在画布上书写文字,

第一个参数为写字坐标;

第二个参数为要写的字符;

第三个参数为字的颜色(前文已构造,也可设置为每个字不同颜色)。

运行代码查看效果:

效果尚可,但总觉得缺少点什么?

3. 添加干扰元素。

既然是验证码,必须具备一定识别难度,上述过于简单的验证码显然不符合要求。

此步骤需导入random模块,因为干扰元素是不规则随机生成的。

import random
from PIL import Image, ImageDraw, ImageFont

# 省略第一步代码

# 省略第二步代码

#使用point函数绘制噪点
for i in range(0, 100):
    xy = (random.randrange(0, width), random.randrange(0, height))
    fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
    draw.point(xy, fill=fill)
    
#释放画笔
del draw   
im.show()

代码解析:

import random

别忘了导入random模块。

for i in range(0, 100):
    xy = (random.randrange(0, width), random.randrange(0, height))
    fill = (255, 255, 255)
    draw.point(xy, fill=fill)

一个执行100次的for循环,

xy变量为绘制干扰点的坐标值。

fill变量为噪点颜色,同样遵循RGB标准。

draw.point用于绘制点。

该for循环次数越多,画布上的噪点也相应增多。

运行代码查看噪点效果:

感觉仍略显简单,尝试将循环次数改为1000次:

10000次!

这已经足够了。

4. 增加更多干扰元素。

此步骤将各个参数与random模块结合,使验证码更难辨认。

import random
from PIL import Image, ImageDraw, ImageFont


bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
width = 400
height = 100

im = Image.new('RGB',(width,height),bg_color)
# 创建画笔对象
draw = ImageDraw.Draw(im)

# 构造字体对象
font = ImageFont.truetype('./ziti.ttf', 100)
# font = ImageFont.load_default().font
# 构造字体颜色
fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
# 绘制4个字
string = 'MSBC'
draw.text((random.randint(10, 30), (random.randint(0, 10))), string[0], font=font, fill=fontcolor)
draw.text((random.randint(90, 130), (random.randint(0, 10))), string[1], font=font, fill=fontcolor)
draw.text((random.randint(180, 230), (random.randint(0, 10))), string[2], font=font, fill=fontcolor)
draw.text((random.randint(270, 330), (random.randint(0, 10))), string[3], font=font, fill=fontcolor)

#调用画笔的point()函数绘制噪点
for i in range(0, 10000):
    xy = (random.randrange(0, width), random.randrange(0, height))
    fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
    draw.point(xy, fill=fill)

#释放画笔
del draw
im.show()

字体颜色、噪点颜色及文本位置均结合了random模块,效果图如下:

5. 验证码与随机字符结合。

此步骤需将上述代码封装到函数中,大致重构如下:

# 使用for循环生成文本字符

# 生成验证码图片的函数,参数就是上面生成的文本

# 调用生成验证码图片函数

重构后:

import random
from PIL import Image, ImageDraw, ImageFont

string = ''
#随机选取4个值作为验证码
rand_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
for i in range(0, 4):
    string += rand_str[random.randrange(0, len(rand_str))]


def gen_verify_img(text):
    bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
    width = 400
    height = 100

    im = Image.new('RGB',(width,height),bg_color)
    # 创建画笔对象
    draw = ImageDraw.Draw(im)

    # 构造字体对象
    font = ImageFont.truetype('./ziti.ttf', 100)
    # font = ImageFont.load_default().font
    # 构造字体颜色
    fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
    # 绘制4个字
    draw.text((random.randint(10, 30), (random.randint(0, 10))), string[0], font=font, fill=fontcolor)
    draw.text((random.randint(90, 130), (random.randint(0, 10))), string[1], font=font, fill=fontcolor)
    draw.text((random.randint(180, 230), (random.randint(0, 10))), string[2], font=font, fill=fontcolor)
    draw.text((random.randint(270, 330), (random.randint(0, 10))), string[3], font=font, fill=fontcolor)

    #调用画笔的point()函数绘制噪点
    for i in range(0, 10000):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
        draw.point(xy, fill=fill)

    #释放画笔
    del draw
    im.show()

# 调用函数
gen_verify_img(string)

将原代码中的string变量移至函数外,作为函数传入参数,

再使用for循环随机选取4个字符。

string = ''
#随机选取4个值作为验证码
rand_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
for i in range(0, 4):
    string += rand_str[random.randrange(0, len(rand_str))]

再次运行代码:

上述验证码是DZNO还是DZN0?

6. 验证码本地保存(可选)。

在Web开发登录操作及训练验证码识别神经网络时,需要大量验证码图片。

因此,需将大量验证码图片文件批量保存至本地。

完整代码如下:

import random
from PIL import Image, ImageDraw, ImageFont


def gen_verify_img(text):
    bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
    width = 400
    height = 100

    im = Image.new('RGB',(width,height),bg_color)
    # 创建画笔对象
    draw = ImageDraw.Draw(im)

    # 构造字体对象
    font = ImageFont.truetype('./ziti.ttf', 100)
    # font = ImageFont.load_default().font
    # 构造字体颜色
    fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
    # 绘制4个字
    draw.text((random.randint(10, 30), (random.randint(0, 10))), string[0], font=font, fill=fontcolor)
    draw.text((random.randint(90, 130), (random.randint(0, 10))), string[1], font=font, fill=fontcolor)
    draw.text((random.randint(180, 230), (random.randint(0, 10))), string[2], font=font, fill=fontcolor)
    draw.text((random.randint(270, 330), (random.randint(0, 10))), string[3], font=font, fill=fontcolor)

    #调用画笔的point()函数绘制噪点
    for i in range(0, 10000):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
        draw.point(xy, fill=fill)

    #释放画笔
    del draw
    # im.show()
    im.save(f'./{text}.png','png')


for i in range(100):
    string = ''
    #随机选取4个值作为验证码
    rand_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    for i in range(0, 4):
        string += rand_str[random.randrange(0, len(rand_str))]
    gen_verify_img(string)
    print(f'{string} 验证码生成成功!!')

最后再次运行:

部分验证码展示:

注:若对本文代码进行变形或改写,可能会得到更多样化的验证码,具体发挥取决于屏幕前的你。

以上就是利用Python生成随机验证码的详细教程,更多关于Python验证码的资料请关注本站其他相关文章!

相关标签:

本站声明

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

Python 相关产品和应用

全部下载

专题列表