1.写作由来
最近练习做一个电商项目,在注册页面准备加一个验证码功能。之前虽然也写过一个简单的验证码生成函数,但如今来看,真是有些‘勉强’,于是结合网上的一些文章,重新改良了一番。
2.实现思路
2.1制作验证码,我们首先得把验证码所必须的元素搞清楚。下面是我认为必需的一些参数。
参数名 | 参数含义 |
---|---|
width | 生成图片的宽度 |
height | 生成图片的高度 |
bgColor | 生成图片的背景色 |
num | 验证码字符个数 |
fontPath | 字体路径 |
fontSize | 字体大小 |
code | 验证码内容(作为返回值,用于验证) |
img | 生成图片对象 |
savePath | 生成图片的保存路径 |
2.2弄清楚参数,还要考虑下验证码的呈现方式。如:字符随机产生、颜色随机更换、字符位置随机改变、干扰线的数量、噪点的数量…考虑清楚这些,便可以着手敲代码了。
3.代码实现
# coding:utf-8
import random
import os
import string
import json
from PIL import Image, ImageDraw, ImageFont
# 将随机函数赋给变量 rdint
rdint = random.randint
class vertifyCode():
def __init__(self, width, height, bgColor, num, fontPath, fontSize, savePath):
self.width = width # 生成图片宽度
self.height = height # 生成图片高度
self.bgColor = bgColor # 生成图片背景颜色
self.num = num # 验证码字符个数
self.fontPath = fontPath # 字体路径
self.fontSzie = fontSize # 字体大小
self.code = '' # 验证内容
self.img = Image.new('RGB', (self.width, self.height), self.bgColor) # 生成图片对象
self.savePath = savePath #生成图片的保存路径
# 获取随机颜色,RGB格式
def get_random_Color(self):
c1 = rdint(50, 150)
c2 = rdint(50, 150)
c3 = rdint(50, 150)
return (c1, c2, c3)
# 随机生成1位字符,作为验证码内容
def get_random_char(self):
c = ''.join(random.sample(string.ascii_letters + string.digits, 1))
self.code += c
return c
# 生成随机位置(x,y)
def get_random_xy(self):
x = rdint(0, int(self.width))
y = rdint(0, int(self.height))
return (x, y)
# 根据字体文件生成字体,无字体文件则生成默认字体
def get_font(self):
if self.fontPath:
if os.path.exists(self.fontPath):
if self.fontSzie and self.fontSzie > 0 and self.fontSzie < self.height:
size = self.fontSzie
else:
size = rdint(int(self.height /1.5), int(self.height - 10))
font = ImageFont.truetype(self.fontPath, size)
return font
raise Exception('字体文件不存在或路径错误', self.fontPath)
return ImageFont.load_default().font
# 图片旋转
def rotate(self):
deg = int(self.height / 3) # 旋转角度
self.img = self.img.rotate(rdint(0, deg), expand=0)
# 画n条干扰线
def drawLine(self, n):
draw = ImageDraw.Draw(self.img)
for i in range(n):
draw.line([self.get_random_xy(), self.get_random_xy()],
self.get_random_Color())
del draw
# 画n个干扰点
def drawPoint(self, n):
draw = ImageDraw.Draw(self.img)
for i in range(n):
draw.point([self.get_random_xy()], self.get_random_Color())
del draw
# 写验证码内容
def drawText(self, position, char, fillColor):
draw = ImageDraw.Draw(self.img)
draw.text(position, char, font=self.get_font(), fill=fillColor)
del draw
# 生成验证码图片,并返回图片对象
def getVertifyImg(self):
x_start = 2
y_start = 0
for i in range(self.num):
x = x_start + i * int(self.width / (self.num))
y = rdint(y_start, int(self.height / 3))
self.drawText((x, y), self.get_random_char(),
self.get_random_Color())
self.drawLine(3)
self.drawPoint(60)
return self.img
# 将图片保存到内存,便于前台点击刷新
# 将验证码保存到session中,返回内存中的图片数据
def saveInMemory(self, request):
img = self.getVertifyImg()
request.session['code'] = self.code.lower()
f = BytesIO() # 开辟内存空间
img.save(f, 'png')
return f.getvalue()
# 将图片保存在本地,并以json格式返回验证码内容
def saveInLocal(self):
img = self.getVertifyImg()
try:
img.save(self.savePath)
except:
raise NotADirectoryError('保存路径错误或不存在:' + self.savePath)
return json.dumps({'code': self.code})
4.效果图
博主其他文章推荐:
[1] 【python实用特性】- 迭代、可迭代对象、迭代器