python验证码生成并临时存储redis

48 篇文章 1 订阅
3 篇文章 0 订阅
1.生成随机字符拼接成验证码
import random

def rand_code(num):
	'''
	生成验证码
	'''
	code = ''
	i = 0
	while i < num:
		flag = random.randrange(0,3)
		if flag == 0:
			code += str(random.randrange(0,10))
		elif flag == 1:
			# 大写字母的ASCII:65-90 chr()函数ASCII转字母,ord()函数字母转ASCII
			code += chr(random.randrange(65, 91))
		else:
			# 生成小写字母:97-120
			code += chr(random.randrange(97,123))
		i+=1
	return code

返回结果:

>>> rand_code(4)
'Yk39'
>>> rand_code(5)
'H8PC5'
>>> rand_code(6)
'4L50P4'

其中:

# random.randrange(a, b)生成[a,b)任意值
# random.randrange(a, b, 1)生成[a,b)中的步长为1的随机值
# random.randint(a, b)生成[a,b]任意值
2.将验证码生产图片

第一种方式,基于PIL图片生成库:

import os
from PIL import Image, ImageDraw, ImageFont
def create_img():
	'''
	生成图片
	'''
	code = rand_code(num)
	base_path = os.getcwd()
	img_file = 'code_{}.png'.format(code)
	img_path = os.path.join(base_path, 'app/fmdata/imgs/' + img_file)
	if not os.path.exists(img_path):
		font = ImageFont.truetype('/font/SIMFANG.TTF', 35) # 字体路径、字体大小
		img = Image.new('RGB', (200, 40), (255,180,0)) # 图片类型、大小、颜色
		draw = ImageDraw.Draw(img)
		for i in range(4):
			draw.text(( (200 / num) * i + 10 + random.randint(-10, 10),
			random.randint(0, 10)), code[i], (255,0,0), font=font) # 格式下字符显示位置(位置、元素、颜色、字体)
		# draw.text((0,0), self.code, (255,0,0),font=font)
		# img.show()
		img.save(img_path)

第二种方式,用三方库captcha生成比较好看的验证码:
官方demo:

from io import BytesIO
from captcha.audio import AudioCaptcha
from captcha.image import ImageCaptcha

audio = AudioCaptcha(voicedir='/path/to/voices')
image = ImageCaptcha(fonts=['/path/A.ttf', '/path/B.ttf'])

data = audio.generate('1234')
assert isinstance(data, bytearray)
audio.write('1234', 'out.wav')

data = image.generate('1234')
assert isinstance(data, BytesIO)
image.write('1234', 'out.png')

实例:

import os
from captcha.image import ImageCaptcha
def create_img():
	'''
	生成图片
	'''
	code = rand_code(num)
	base_path = os.getcwd()
	img_file = 'code_{}.png'.format(code)
	img_path = os.path.join(base_path, 'app/fmdata/imgs/' + img_file)
	new_code =''.join([j+' ' for j in code])[0:-1] #让字符空格分开,使得生成的验证图片更便于查看,不会重叠
	if not os.path.exists(img_path):
		image = ImageCaptcha().generate_image(new_code )
		# image .show()
		image.save(img_path)
3.将验证码临时存入redis,并设置过期时间用于验证
import redis
def connect_redis():
	'''
	链接redis
	'''
	pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
	return redis.Redis(connection_pool=pool)

def save_redis(code):
	'''
	把临时生成的验证码存储到redis
	'''
	rd = connect_redis()
	rd.set('code_'+code, code) # 把验证码存储起来
	rd.expire('code_'+code, 60*5) # 验证码 5分钟后时效
4.验证提交的验证码是否正确
def check_code(code):
	'''
	检测验证码是否过期:用于登录或者前端验证使用
	'''
	rd = connect_redis()
	msg = True
	if not rd.get('code_'+code):
		msg = False

	return msg

以上就完成了验证码的生成、临时存储、验证等,如果想更好的使用请结合自身的项目进行改良。
生成的图片示例:

1.PIL生成的图片:

在这里插入图片描述

2.captcha生成的图片:

在这里插入图片描述
最后附上完整demo源码:

import os
import random
from PIL import Image, ImageDraw, ImageFont
import redis
from datetime import datetime
import time

class CreatCode:
	def __init__(self, num):
		self.num = num
		self.code = ""
		self.img_path = ''

	def rand_code(self):
		'''
		生成验证码
		'''
		i = 0
		while i < self.num:
			flag = random.randrange(0,3)
			if flag == 0:
				self.code += str(random.randrange(0,10))
			elif flag == 1:
				# 大写字母的ASCII:65-90 chr()函数ASCII转字母,ord()函数字母转ASCII
				self.code += chr(random.randrange(65, 91))
			else:
				# 生成小写字母:97-120
				self.code += chr(random.randrange(97,123))
			i+=1

	def create_img(self):
		'''
		生成图片
		'''
		self.rand_code()
		base_path = os.getcwd()
		img_file = 'code_{}.png'.format(self.code)
		self.img_path = os.path.join(base_path, 'app/fmdata/imgs/' + img_file)
		if not os.path.exists(self.img_path):
			font = ImageFont.truetype('/home/www/finance/app/fmdata/imgs/SIMFANG.TTF', 35)
			img = Image.new('RGB', (200, 40), (255,180,0))
			draw = ImageDraw.Draw(img)
			for i in range(4):
				draw.text(( (200 / self.num) * i + 10 + random.randint(-10, 10),
				random.randint(0, 10)), self.code[i], (255,0,0), font=font) # 格式下字符显示位置
			# draw.text((0,0), self.code, (255,0,0),font=font)
			# img.show()
			img.save(self.img_path)
		save_redis(self.code) # 验证码保存到缓存

		return self.img_path, self.code
	
	def create_img_plus(self):
		'''
		生成图片
		'''
		code = rand_code(num)
		base_path = os.getcwd()
		img_file = 'code_{}.png'.format(code)
		img_path = os.path.join(base_path, 'app/fmdata/imgs/' + img_file)
		new_code =''.join([j+' ' for j in self.code])[0:-1] #让字符空格分开,使得生成的验证图片更便于查看,不会重叠
		if not os.path.exists(img_path):
			image = ImageCaptcha().generate_image(new_code )
			# image .show()
			image.save(img_path)
		save_redis(self.code) # 验证码保存到缓存

		return self.img_path, self.code


def connect_redis():
	'''
	链接redis
	'''
	pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
	return redis.Redis(connection_pool=pool)

def save_redis(code):
	'''
	把临时生成的验证码存储到redis
	'''
	rd = connect_redis()
	rd.set('code_'+code, code) # 把验证码存储起来
	rd.expire('code_'+code, 60*5) # 验证码 5分钟后时效


def check_code(code):
	'''
	检测验证码是否过期:用于登录或者前端验证使用
	'''
	rd = connect_redis()
	msg = True
	if not rd.get('code_'+code):
		msg = False

	return msg

3.PIL生成gif图片:

以下借鉴于:https://blog.csdn.net/y472360651/article/details/90259372
依赖包:

pip install pillow
pip install imageio

完整代码:

import os
import random
from io import BytesIO

import imageio
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont


class GifCodeImage(object):
    def __init__(self, width=150, height=35, code_count=4, font_size=35, point_count=20, line_count=6, frame_count=30):
        """

        :param width: 图片宽度
        :param height: 图片高度
        :param code_count: 验证码位数
        :param font_size: 字体大小
        :param point_count: 噪点数量
        :param line_count: 噪线数量
        :param frame_count: gif的帧数
        """
        self.width = width
        self.height = height
        self.code_count = code_count
        self.font_size = font_size
        self.point_count = point_count
        self.line_count = line_count
        self.frame_count = frame_count

    @staticmethod
    def get_random_color():
        """
        获取一个随机颜色(r,g,b)格式的
        :return:
        """
        c1 = random.randint(0, 255)
        c2 = random.randint(0, 255)
        c3 = random.randint(0, 255)
        return c1, c2, c3

    @staticmethod
    def get_random_str():
        """
        获取一个随机字符串,每个字符的颜色也是随机的
        :return:
        """
        random_num = str(random.randint(0, 9))
        random_low_alpha = chr(random.randint(97, 122))
        random_upper_alpha = chr(random.randint(65, 90))
        random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
        return random_char

    def get_code_and_image(self):
        """
        生成验证码与动画帧数
        :return:
        """
        code_str_list = []
        for _ in range(self.code_count):
            s = self.get_random_str()
            code_str_list.append(s)

        # bg_color = self.get_random_color()

        bg_color = 255,255,255

        frame_list = []
        for item in range(self.frame_count):
            image = Image.new('RGB', (self.width, self.height), bg_color)
            draw = ImageDraw.Draw(image)

            # path = os.path.join(os.getcwd(), "cabourgot-bold.otf")
            path = 'C:/Windows/Fonts/simhei.ttf' # 字体目录
            font = ImageFont.truetype(path, size=self.font_size)

            for i, code in enumerate(code_str_list):
                # v = random.randint(-7, 2)
                v = random.randint(-7, 10)
                x = random.randint(14, 22)
                draw.text((x + i * 30, v), code, self.get_random_color(), font=font)

            # 噪点噪线
            # 划线
            for i in range(self.line_count):
                x1 = random.randint(0, self.width)
                x2 = random.randint(0, self.width)
                y1 = random.randint(0, self.height)
                y2 = random.randint(0, self.height)
                draw.line((x1, y1, x2, y2), fill=self.get_random_color())

            # 画点
            for i in range(self.point_count):
                draw.point([random.randint(0, self.width), random.randint(0, self.height)],
                           fill=self.get_random_color())
                x = random.randint(0, self.width)
                y = random.randint(0, self.height)
                draw.arc((x, y, x + 4, y + 4), 0, 90, fill=self.get_random_color())

            f = BytesIO()
            image.save(f, "png")
            data = f.getvalue()
            f.close()

            data = imageio.imread(data, format="png")
            frame_list.append(data)

        return frame_list, "".join(code_str_list)


if __name__ == "__main__":
    img = GifCodeImage()
    frame_list, code_str = img.get_code_and_image()
    imageio.mimsave("code.gif", frame_list, 'GIF', duration=0.35)
    print(code_str)

效果如下图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值