python3 实现基础图形验证码

每日一句

When it rains , look for rainbows.When it’s dark,look for stars.

生成随机图片验证码,可参考如下代码1所示:

import random
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont, ImageFilter
# pip install pillow

class VerifyCode():

    def __init__(self):
        self._letter_cases = 'abcdefghjkmnpqrstuvwxy'
        self._upper_cases = self._letter_cases.upper()
        self._numbers = ''.join(map(str, range(3, 10)))
        pass

    # 需要把monaco.ttf放到此程序目录下,下载地址https://github.com/todylu/monaco.ttf

    def createCodeImage(self, size=(120, 30), img_type='jpg',
                        mode='RGB', bg_color=(255, 255, 255), fg_color=(0, 0, 255),
                        font_size=18, font_type='./Monaco.ttf',
                        length=4, draw_lines=True, n_line=(1, 2),
                        draw_points=True, point_chance=2):
        width, height = size
        # 定义使用Image类实例化一个长120,宽30,基于RGB的(255.255.255)颜色的图片
        img = Image.new(mode, size, bg_color)
        # 创建画笔,用于在图片上生成内容
        draw = ImageDraw.Draw(img)

        def get_chars():
            return random.sample(self._letter_cases, length)

        def creat_line():
            line_num = random.randint(*n_line)  # sign that the param is a list

            for i in range(line_num):
                begin = (random.randint(
                    0, size[0]), random.randint(0, size[1]))
                end = (random.randint(0, size[0]), random.randint(0, size[1]))
                draw.line([begin, end], fill=(0, 0, 0))
        # 在图片上生成点
        def create_points():
            chance = min(100, max(0, int(point_chance)))
            for w in range(width):
                for h in range(height):
                    tmp = random.randint(0, 100)
                    if tmp > 100 - chance:
                        draw.point((w, h), fill=(0, 0, 0))
        # 在图片上生成字符
        def create_strs():
            c_chars = get_chars()
            strs = ' %s ' % ' '.join(c_chars)
            font = ImageFont.truetype(font_type, font_size)
            font_width, font_height = font.getsize(strs)
            draw.text(((width - font_width) / 3, (height - font_height) / 3),
                      strs, font=font, fill=fg_color)
            return ''.join(c_chars)

        if draw_lines:
            creat_line()
        if draw_points:
            create_points()
        strs = create_strs()

        params = [1 - float(random.randint(1, 2)) / 100,
                  0,
                  0,
                  0,
                  1 - float(random.randint(1, 10)) / 100,
                  float(random.randint(1, 2)) / 500,
                  0.001,
                  float(random.randint(1, 2)) / 500
                  ]
        img = img.transform(size, Image.PERSPECTIVE, params)
        img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
        return img, strs


def cre_code():
    vecode = VerifyCode()
    code_img, capacha_code = vecode.createCodeImage()
    msstream = BytesIO()
    code_img.save(msstream, "gif")
    code = msstream.getvalue()

    return code, capacha_code


image, text = cre_code()
# image 为二进制流

print(image)
print("图片验证码:%s" % text)
# with open('./ image.gif ', 'wb') as pic:
#     pic.write(image)

为了服务端验证,还需要在请求验证码时请求一个ID,供后续服务器验证ID和验证码的值。
参考代码2如下:

from CAPTCHA import cre_code


class ImageCodeView(APIView):
    """图片验证码"""

    def get(self, request, vcode_id):
        # 生成验证码图片
        image, text = cre_code()

        # 保存真实值
        # redis_conn = get_redis_connection('verify_codes')
        # redis_conn.setex("img_%s" % vcode_id, 5 * 60, text)

        print("图片验证码:%s" % text)

        # 返回图片
        return HttpResponse(image, content_type='image/gif')

代码1执行的结果参考如下所示:

保存到本地可见如下图片:

No pains, No gains
原文地址:https://www.cnblogs.com/Rightsec/p/15130663.html