python 验证码
python 验证码
pillow 库
pip install pillow
Image.new()
- mode 颜色空间模式,
RGBA
RGB
L
- size 图片尺寸
- color 图片填充颜色, 可以是 red, green
from PIL import Imagecaptcha = Image.new('RGB', (1080, 900), (255,255,255))
Image.save()
- fp 本地文件名
- format 制定文件后缀
from PIL import Imagecaptcha = Image.new('RGB', (1080, 900), (255,255,255))# captcha.save('captcha.png')captcha.save('captcha', format='png')
Image.show()
显示图片,会调用电脑自带的显示图片的软件。
ImageFont.truetype()
加载一个字体文件。生成一个字体对象。
from PIL import ImageFont# 字体文件路径 字体大小font = ImageFont.truetype('simkai.ttf', 16)
ImageDraw.Draw()
生成画笔对象
from PIL import Image, ImageDrawcaptcha = Image.new('RGB', (1080, 900), 'red')draw = ImageDraw.Draw(captcha)
ImageDraw.Draw().text()
在图片上绘制给定的字符
from PIL import Image, ImageDraw, ImageFontcaptcha = Image.new('RGB', (1080, 900), 'red')font = ImageFont.truetype('simkai.ttf', 16)draw = ImageDraw.Draw(captcha)# 字符绘制位置, 绘制的字符, 制定字体, 字符颜色draw.text((0,0), 'hello world', font=font, fill='black')
ImageDraw.Draw().line()
在图片上绘制线条
from PIL import Image, ImageDraw, ImageFontcaptcha = Image.new('RGB', (1080, 900), 'red')draw = ImageDraw.Draw(captcha)# 线条起点, 线条终点draw.line([(0,0),(1080,900)], fill='black')
ImageDraw.Draw().point()
在图片上绘制点
from PIL import Image, ImageDraw, ImageFontcaptcha = Image.new('RGB', (1080, 900), 'red')font = ImageFont.truetype('simkai.ttf', 16)draw = ImageDraw.Draw(captcha)# 点的位置, 颜色draw.point((500,500), fill='black')
制作验证码
string模块
- string.ascii_letters: 得到a-zA-Z所有字符
- string.digits: 得到0-9所有数字
random.sample()
从第一个参数中随机获取字符。获取个数有第二个参数指定。
代码
#!/usr/bin/env python3# -*- coding: utf-8 -*-# vim:fenc=utf-8# Create Time: 2019-08-30 14:11:48# Last Modified: 2019-08-30 14:43:37import stringimport randomfrom PIL import Image, ImageFont, ImageDrawclass Captcha(): ''' 初始化一些参数 captcha_size: 验证码图片尺寸 font_size: 字体大小 text_number: 验证码中字符个数 line_number: 线条个数 background_color: 验证码的背景颜色 sources: 取样字符集。验证码中的字符就是随机从这个里面选取的 save_format: 验证码保存格式 ''' def __init__(self, captcha_size=(150, 100), font_size=30, text_number=4, line_number=4, background_color=(255, 255, 255), sources=None, save_format='png'): self.text_number = text_number self.line_number = line_number self.captcha_size = captcha_size self.background_color = background_color self.font_size = font_size self.format = save_format if sources: self.sources = sources else: self.sources = string.ascii_letters + string.digits def get_text(self): '''随机从sources获取字符''' text = random.sample(self.sources, k=self.text_number) return ''.join(text) def get_font_color(self): '''随机获取绘制字符的颜色''' font_color = (random.randint(0, 150), random.randint(0, 150), random.randint(0, 150)) return font_color def get_line_color(self): '''随机获取干扰线条的颜色''' line_color = (random.randint(0, 250), random.randint(0, 255), random.randint(0, 250)) return line_color def draw_text(self, draw, text, font, captcha_width, captcha_height, spacing=20): ''' 绘制文字的方法 在图片上绘制传入的字符 :param draw: 画笔对象 :param text: 绘制的所有字符 :param font: 字体对象 :param captcha_width: 验证码的宽度 :param captcha_height: 验证码的高度 :param spacing: 每个字符的间隙 :return: ''' # 得到这一窜字符的高度和宽度 text_width, text_height = font.getsize(text) # 得到每个字体的大概宽度 every_value_width = int(text_width / 4) # 这一窜字符的总长度 text_length = len(text) # 每两个字符之间拥有间隙,获取总的间隙 total_spacing = (text_length-1) * spacing if total_spacing + text_width >= captcha_width: raise ValueError("字体加中间空隙超过图片宽度!") # 获取第一个字符绘制位置 start_width = int((captcha_width - text_width - total_spacing) / 2) start_height = int((captcha_height - text_height) / 2) # 依次绘制每个字符 for value in text: position = start_width, start_height print(position) # 绘制text draw.text(position, value, font=font, fill=self.get_font_color()) # 改变下一个字符的开始绘制位置 start_width = start_width + every_value_width + spacing def draw_line(self, draw, captcha_width, captcha_height): ''' 绘制线条 :param draw: 画笔对象 :param captcha_width: 验证码的宽度 :param captcha_height: 验证码的高度 :return: ''' # 随机获取开始位置的坐标 begin = (random.randint(0, captcha_width/2), random.randint(0, captcha_height)) # 随机获取结束位置的坐标 end = (random.randint(captcha_width/2, captcha_width), random.randint(0, captcha_height)) draw.line([begin, end], fill=self.get_line_color()) def draw_point(self, draw, point_chance, width, height): ''' 绘制小圆点 :param draw: 画笔对象 :param point_chance: 绘制小圆点的几率 概率为 point_chance/100 :param width: 验证码宽度 :param height: 验证码高度 :return: ''' # 按照概率随机绘制小圆点 for w in range(width): for h in range(height): tmp = random.randint(0, 100) if tmp < point_chance: draw.point((w, h), fill=self.get_line_color()) def make_captcha(self): '''制作验证码''' # 获取验证码的宽度, 高度 width, height = self.captcha_size # 生成一张图片 captcha = Image.new('RGB', self.captcha_size, self.background_color) # 获取字体对象 font = ImageFont.truetype('simkai.ttf', self.font_size) # 获取画笔对象 draw = ImageDraw.Draw(captcha) # 得到绘制的字符 text = self.get_text() # 绘制字符 self.draw_text(draw, text, font, width, height) # 绘制线条 for i in range(self.line_number): self.draw_line(draw, width, height) # 绘制小圆点 10是概率 10/100, 10%的概率 self.draw_point(draw, 10, width, height) print(self.format) # 保存图片 captcha.save(f"captcha.{self.format}") # 显示图片 # captcha.show()if __name__ == '__main__': c = Captcha() c.make_captcha()