Python 之生成验证码

一、代码

import random
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont, ImageFilter


class Captcha:
    def __init__(self, width, height, code_num=4, code_type=1, font_size=24, is_blur=True, font='Arial.ttf',
                 x_offset=None, y_offset=None):
        """
        :param width: 验证码图片宽度
        :param height: 验证码图片高度
        :param code_num: 验证码字符个数 默认是4个
        :param code_type: 验证码类型  1字母或数字 2全字母 alpha 3全数字 digit
        :param font_size: 验证码字体尺寸
        :param is_blur: 验证码图片是否模糊处理
        :param font: 字体全路径  例如 '/Library/Fonts/Arial.ttf'
        :param x_offset: 验证码字符水平偏移量 默认自动计算
        :param y_offset: 验证码字符垂直偏移量 默认自动计算
        """
        self.width = width
        self.height = height
        self.code_num = code_num
        self.code_type = code_type
        self.font_size = font_size
        self.is_blur = is_blur
        self.font = font
        self.x_offset = x_offset
        self.y_offset = y_offset

    def save_image(self, image_path, image_type='png'):
        image = self._get_captcha_image()
        image.save(image_path, image_type)

    def save_bytes_io(self, image_type='png'):
        io_obj = BytesIO()
        image = self._get_captcha_image()
        image.save(io_obj, image_type)
        return io_obj

    def _get_captcha_image(self):
        image = Image.new('RGB', (self.width, self.height), (255, 255, 255))
        # 创建Font对象:
        font = ImageFont.truetype(self.font, self.font_size)
        # 创建Draw对象:
        draw = ImageDraw.Draw(image)
        # 填充每个像素:
        for x in range(self.width):
            for y in range(self.height):
                draw.point((x, y), fill=self._get_img_color())
        xw = self.width // self.code_num
        x_offset = self.x_offset if self.x_offset else ((self.width - self.code_num * self.font_size - (
                    self.code_num - 1) * (xw - self.font_size)) // 2) + (xw - self.font_size) // 3
        y_offset = self.y_offset if self.y_offset else (self.height - self.font_size) // 2
        # 输出文字:
        self.code = []
        for t in range(self.code_num):
            random_code = self._get_random_code()
            self.code.append(random_code)
            draw.text((xw * t + x_offset, y_offset), random_code, fill=self._get_font_color(), font=font)
        # 模糊:
        if self.is_blur:
            image = image.filter(ImageFilter.BLUR)
        return image

    def _get_random_code(self):
        if self.code_type == 1:
            return self._get_alpha_digit()
        elif self.code_type == 2:
            return self._get_alpha()
        elif self.code_type == 3:
            return self._get_digit()
        return self._get_alpha_digit()

    def _get_alpha_digit(self):
        return random.choice([self._get_alpha(), self._get_digit()])

    def _get_alpha(self):
        return random.choice([chr(random.randint(65, 90)), chr(random.randint(97, 122))])

    def _get_digit(self):
        return str(random.randint(0, 9))

    def _get_img_color(self):
        return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

    def _get_font_color(self):
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

二、使用

path = os.path.dirname(__file__)
captcha = Captcha(160, 35, is_blur=False, font= path + "/captcha/Arial.ttf", code_num=5)
captcha.save_image(path + '/code.png')
print(captcha.code)
    
print(captcha.save_bytes_io())

 

posted @ 2023-04-07 16:04  样子2018  阅读(161)  评论(0编辑  收藏  举报