Python生成随机验证码完整教程:从基础到抗干扰实现
本文详细讲解如何利用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验证码的资料请关注本站其他相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









