python用PIL制作复杂的验证码

因为注册登陆系统要验证码,就自己用python做了一个,留着以后用吧
有正常的干扰元素,带字符旋转

flag:还差做字符扭曲和自定义输入

import random
from PIL import Image, ImageDraw, ImageFont


class pil():

    def __init__(self, width, height, mode=None, color=None):

        """
        初始化--> 画文本--> (画干扰效果)--> 显示
        :param mode: mode-->默认RGBA
        :param width: 验证码的宽
        :param height: 验证码的高
        :param color: (num, num, num)
        """
        self.mode = mode
        if mode:    # 默认RGBA
            self.mode = mode

        else:
            self.mode = 'RGBA'
        self.width = width
        self.height = height
        self.color = None
        if color:   # 默认(255, 255, 255)
            self._color = color

        else:
            self._color = (255, 255, 255)

        # 定义使用Image类实例化一个图片
        self.img = Image.new(mode=self.mode, size=(self.width, self.height), color=self._color)

    def draw_out(self):
        # 把生成的图片保存为"pic.png"格式
        with open('pic.png', 'wb') as f:
            self.img.save(f, format='png')

        # 显示图片
        self.img.show()

    # 画文本
    def draw_text(self, font_path, num, number=True, a_font=False, A_font=False):
        """
        若要添加字样,则设为true,数字默认开启
        :param font_path: 字样文件
        :param num: 验证码字符个数
        :param number: 是否开启数字
        :param a_font: 是否开启小写字母
        :param A_font: 是否开启大写字母
        :return: None
        """
        self.img = Image.new(mode=self.mode, size=(self.width, self.height), color=self._color)
        draw = ImageDraw.Draw(self.img, mode=self.mode)

        # 定义字体
        font1 = font_path
        font = ImageFont.truetype(font1, 60)    # 字体大小

        data = self.get_font(number=number, a_font=a_font, A_font=A_font)
        for i in range(num):
            # 数字,大写字母,小谢字母
            text = random.choice(data)
            color = self.get_color()
            draw.text([i * 50 + 12, -10], text, color, font=font)

    def draw_text_rotate(self, font_path, num, number=True, a_font=False, A_font=False):
        """
        若要添加字样,则设为true,数字默认开启
        :param font_path: 字样文件
        :param num: 验证码字符个数
        :param number: 是否开启数字
        :param a_font: 是否开启小写字母
        :param A_font: 是否开启大写字母
        :return: None
        """

        self.img = Image.new(mode=self.mode, size=(self.width, self.height), color=self._color)

        font1 = font_path
        font = ImageFont.truetype(font1, 60)

        data = self.get_font(number=number, a_font=a_font, A_font=A_font)
        for i in range(num):
            # 数字,大写字母,小谢字母
            text = random.choice(data)
            color = self.get_color()

            global IMG
            img0 = Image.new(mode=self.mode, size=(self.width, self.height),
                             color=(255, 255, 255))
            draw0 = ImageDraw.Draw(img0, mode='RGBA')
            draw0.text((0, 0), text, color, font=font)

            # 获得一个旋转字
            img1 = img0.rotate(random.uniform(-35, 35), Image.BILINEAR,
                               translate=((i * 65) + 25, 0), center=(0, 0),
                               expand=0)
            if i == 0:  # 当前旋转字与上一个叠加
                IMG = img1
            else:
                IMG = Image.composite(img1, IMG, img1)

        blank = Image.new(mode='RGBA', size=IMG.size, color=(255,) * 3)    # 白背景
        self.img = Image.composite(IMG, blank, IMG)     # 补全旋转字的空缺

    # 画干扰点
    def draw_point(self, num):
        # 生成img该对象上的画笔
        draw = ImageDraw.Draw(self.img, mode=self.mode)

        for i in range(num):
            x = random.randint(0, self.width)
            y = random.randint(0, self.height)
            color = self.get_color()

            draw.point([x, y], fill=color)
        # self.draw_out()

    # 画干扰园
    def draw_arc(self, num):
        # 生成img该对象上的画笔
        draw = ImageDraw.Draw(self.img, mode=self.mode)

        for i in range(num):
            x = random.randint(0, self.width)
            y = random.randint(0, self.height)
            color = self.get_color()

            draw.arc([x, y, x + 15, y + 15], 0, 360, fill=color)
        # self.draw_out()

    # 画干扰线
    def draw_line(self, num):
        # 生成img该对象上的画笔
        draw = ImageDraw.Draw(self.img, mode=self.mode)

        for i in range(num):
            x1 = random.randint(0, self.width)
            y1 = random.randint(0, self.height)
            x2 = random.randint(0, self.width)
            y2 = random.randint(0, self.height)
            color = self.get_color()

            draw.line([x1, y1, x2, y2], fill=color)
            # self.draw_out()

    def get_font(self, number=False, a_font=False, A_font=False):
        data = []
        if number:
            for i in range(0, 10):
                data.append(str(i))

        if A_font:
            for i in range(65, 91):
                data.append(chr(i))

        if a_font:
            for i in range(97, 123):
                data.append(chr(i))

        return data

    def get_color(self):
        self.color = (random.randint(0, self._color[0]),
                      random.randint(0, self._color[1]), random.randint(0, self._color[2]))
        return self.color


pil = pil(width=190, height=60)

pil.draw_text_rotate(font_path='UbuntuMono-B.ttf', num=3, a_font=True, A_font=True)
# pil.draw_text(font_path='UbuntuMono-B.ttf', num=4, a_font=True, A_font=True)
pil.draw_point(400)
pil.draw_arc(13)
pil.draw_line(6)
pil.draw_out()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值