生成并發送圖檔驗證碼
1. 安裝包
python繪圖需要安裝
pillow
包
pip install pillow
2. 繪圖源代碼
(57行, 裡面的字型需要自己下載下傳和修改)
import random
import string
# Image:一個畫布
# ImageDraw:一個畫筆
# ImageFont:畫筆的字型
from PIL import Image,ImageDraw,ImageFont
# pip install pillow
# Captcha驗證碼
class Captcha(object):
# 生成幾位數的驗證碼
number = 4
# 驗證碼圖檔的寬度和高度
size = (100,30)
# 驗證碼字型大小
fontsize = 25
# 加入幹擾線的條數
line_number = 2
# 建構一個驗證碼源文本
SOURCE = list(string.ascii_letters)
for index in range(0, 10):
SOURCE.append(str(index))
#用來繪制幹擾線
@classmethod
def __gene_line(cls,draw,width,height):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill = cls.__gene_random_color(),width=2)
# 用來繪制幹擾點
@classmethod
def __gene_points(cls,draw,point_chance,width,height):
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=cls.__gene_random_color())
# 生成随機的顔色
@classmethod
def __gene_random_color(cls,start=0,end=255):
random.seed()
return (random.randint(start,end),random.randint(start,end),random.randint(start,end))
# 随機選擇一個字型
@classmethod
def __gene_random_font(cls):
# 這裡的字型可以自己做響應的修改
fonts = [
'verdana.ttf'
]
font = random.choice(fonts)
return 'utils/captcha/'+font
# 用來随機生成一個字元串(包括英文和數字)
@classmethod
def gene_text(cls, number):
# number是生成驗證碼的位數
return ''.join(random.sample(cls.SOURCE, number))
#生成驗證碼
@classmethod
def gene_graph_captcha(cls):
# 驗證碼圖檔的寬和高
width,height = cls.size
# 建立圖檔
# RGB為顔色, A: 透明度
image = Image.new('RGBA',(width,height),cls.__gene_random_color(0,100))
# 驗證碼的字型
font = ImageFont.truetype(cls.__gene_random_font(),cls.fontsize)
# 建立畫筆
draw = ImageDraw.Draw(image)
# 生成字元串
text = cls.gene_text(cls.number)
# 擷取字型的尺寸
font_width, font_height = font.getsize(text)
# 填充字元串
draw.text(((width - font_width) / 2, (height - font_height) / 2),text,font= font,fill=cls.__gene_random_color(150,255))
# 繪制幹擾線
for x in range(0, cls.line_number):
cls.__gene_line(draw, width, height)
# 繪制噪點
cls.__gene_points(draw, 10, width, height)
return (text,image)
3. 背景向前台傳送驗證碼
理一下思路:
- 接收繪圖子產品傳來的圖形驗證碼
- 用 二進制流操作圖檔驗證碼進行傳輸
- 将尋求設定在開始, 這樣才能擷取圖檔驗證碼
- 使用
傳輸二進制流, 并設定文本格式make_response
,在前端顯示content_type="image/png"
from io import BytesIO
@bp.route('/captcha/')
def graph_captcha():
# 擷取圖形驗證碼的 驗證數字和圖檔
text, image = Captcha.gene_graph_captcha()
# BytesIo: 用于操作二進制資料流
out = BytesIO()
# 儲存圖檔 fp:out, format: png
image.save(out, "png")
# 将尋求設定從頭(0)開始, (1)從目前位置開始, (2)從尾部開始尋求
out.seek(0)
resp = make_response(out.read())
# 設定響應的檔案類型
resp.content_type = "image/png"
return resp
4. 前端設定驗證碼
5. jQuery實作點選圖檔更換驗證碼
$(function () {
$("#img-captcha").click(function (event) {
var self = $(this);
var src = self.attr('src');
var newsrc = xtparam.setParam(src, "xx", Math.random());
self.attr('src', newsrc)
});
});
xtparam.js
// xtparam.js
// 粘貼就可以
var xtparam = {
setParam: function (href,key,value) {
// 重新加載整個頁面
var isReplaced = false;
var urlArray = href.split('?');
if(urlArray.length > 1){
var queryArray = urlArray[1].split('&');
for(var i=0; i < queryArray.length; i++){
var paramsArray = queryArray[i].split('=');
if(paramsArray[0] == key){
paramsArray[1] = value;
queryArray[i] = paramsArray.join('=');
isReplaced = true;
break;
}
}
if(!isReplaced){
var params = {};
params[key] = value;
if(urlArray.length > 1){
href = href + '&' + $.param(params);
}else{
href = href + '?' + $.param(params);
}
}else{
var params = queryArray.join('&');
urlArray[1] = params;
href = urlArray.join('?');
}
}else{
var param = {};
param[key] = value;
if(urlArray.length > 1){
href = href + '&' + $.param(param);
}else{
href = href + '?' + $.param(param);
}
}
return href;
}
};