python生成验证码 开箱即用

python生成验证码 开箱即用,第1张

python生成验证码 开箱即用 验证码类
import string
import random
from PIL import Image, ImageDraw, ImageFont


class Captcha:
    def __init__(self, captcha_size=(150, 50),
                 font_size=40, font_style=None, text_number=6,
                 line_number=6, background_color=(255, 255, 255),
                 sources=None):
        """
        :param captcha_size: 验证码Size:tuple
        :param font_size:    字体Size:int
        :param font_style:   字体样式:ttf文件路径
        :param text_number:  验证码数量:int
        :param line_number:  干扰线条数量:int
        :param background_color: 验证码背景:rgb
        :param sources:      验证码源:str
        """
        self.captcha_width = captcha_size[0]
        self.captcha_height = captcha_size[-1]
        self.font_size = font_size
        self.text_number = text_number
        self.line_number = line_number
        self.background_color = background_color
        if font_style:
            self.font_style = font_style
        else:
            self.font_style = 'simkai.ttf'
        if sources:
            self.sources = sources
        else:
            self.sources = string.ascii_letters + string.digits

    def _get_text(self):
        text = random.sample(self.sources, k=self.text_number)
        return ''.join(text)

    def _font_color(self):
        return random.randint(0, 150), random.randint(0, 150), random.randint(0, 150)

    def _other_color(self):
        return random.randint(0, 250), random.randint(0, 250), random.randint(0, 250)

    def _draw_line(self, draw):
        begin = (random.randint(0, self.captcha_width // 2), random.randint(0, self.captcha_height // 2))
        end = (random.randint(self.captcha_width // 2, self.captcha_width),
               random.randint(self.captcha_height // 2, self.captcha_height))
        draw.line([begin, end], fill=self._other_color())

    def _draw_point(self, draw, point_chance):
        for w in range(self.captcha_width):
            for h in range(self.captcha_height):
                tmp = random.randint(0, 100)
                if tmp < point_chance:
                    draw.point((w, h), fill=self._other_color())

    def _draw_text(self, draw, text, font, spacing=20):
        """
        :param draw: 画布对象:ImageDraw
        :param text: 验证码:str
        :param font: 字体对象:ImageFont
        :param spacing: 验证码间隙:int
        """
        # 使用该字体画出来的字符串大小,与字体大小有关
        text_width, text_height = font.getsize(text)

        char_length = int(text_width / self.text_number)
        # 空白之和
        total_spacing = (self.text_number - 1) * spacing
        # 有效区域
        true_width = total_spacing + text_width
        true_height = text_height

        if true_width >= self.captcha_width:
            raise ValueError('字体加中间空隙超过图片总宽度')

        start_width = int((self.captcha_width - true_width) / 2)
        start_height = int((self.captcha_height - true_height) / 2)
        for value in text:
            position = start_width, start_height
            draw.text(position, value, font=font, fill=self._font_color())
            start_width = start_width + char_length + spacing

    def code(self):
        captcha = Image.new('RGB', (self.captcha_width, self.captcha_height), self.background_color)
        font = ImageFont.truetype(self.font_style, self.font_size)
        draw = ImageDraw.Draw(captcha)
        text = self._get_text()

        self._draw_text(draw, text, font, spacing=5)

        for _ in range(self.line_number):
            self._draw_line(draw)

        # 每个坐标的画点概率10%
        self._draw_point(draw, 10)
        return captcha, text
调用
if __name__ == '__main__':
    captcha = Captcha()
    imgObj, code = a.code()
    imgObj.save('test.png')
结果

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5721511.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存