原文?https://www.cyberlight.xyz/passage/python3-flask-validate-picture
記錄純粹通過(guò)Python Flask生成并顯示驗(yàn)證碼唱捣,實(shí)現(xiàn)用戶驗(yàn)證登錄。實(shí)現(xiàn)過(guò)程中我參考了大量相關(guān)教程和筆記,感謝為之分享的各位实胸!
目前對(duì)此的理解不是很深刻黍瞧,先附上實(shí)現(xiàn)的過(guò)程
一.Flask后端
要實(shí)現(xiàn)驗(yàn)證碼辫继,需要用到PIL庫(kù)生成驗(yàn)證碼圖片 腊状,Python3輸入如下命令安裝
pip install pillow
下載ttf格式字體贝奇,放在程序根目錄航棱,然后用以下函數(shù)實(shí)現(xiàn)驗(yàn)證碼生成
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from io import BytesIO
import random
import base64
#驗(yàn)證碼圖片
def validate_picture():
? ? total = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345789'
? ? # 圖片大小130 x 50
? ? width = 130
? ? heighth = 50
? ? # 先生成一個(gè)新圖片對(duì)象
? ? im = Image.new('RGB',(width, heighth), 'white')
? ? # 設(shè)置字體, MicrosoftYaqiHeiLight-2.ttf是我下載的字體睡雇,放在程序根目錄
? ? font = ImageFont.truetype("MicrosoftYaqiHeiLight-2.ttf", 30)
? ? # 創(chuàng)建draw對(duì)象
? ? draw = ImageDraw.Draw(im)
? ? str = ''
? ? # 輸出每一個(gè)文字
? ? for item in range(4):
? ? ? ? text = random.choice(total)
? ? ? ? str += text
? ? ? ? draw.text((-3+random.randint(3,7)+25*item, -3+random.randint(2,7)), text=text, fill='black',font=font )
? ? # 劃幾根干擾線
? ? for num in range(1):
? ? ? ? x1 = random.randint(0, width/2)
? ? ? ? y1 = random.randint(0, heighth/2)
? ? ? ? x2 = random.randint(0, width)
? ? ? ? y2 = random.randint(heighth/2, heighth)
? ? ? ? draw.line(((x1, y1),(x2,y2)), fill='black', width=1)
? ? # 加上濾鏡
? ? im = im.filter(ImageFilter.FIND_EDGES)
? ? return im, str
#生成驗(yàn)證碼實(shí)例的函數(shù)
def run_code():
? ? #生成驗(yàn)證碼,image為驗(yàn)證碼圖片饮醇,code為驗(yàn)證碼文本
? ? image, code = validate_picture()
? ? # 將驗(yàn)證碼圖片以二進(jìn)制形式寫(xiě)入在內(nèi)存中它抱,防止將圖片都放在文件夾中,占用大量磁盤(pán)
? ? buf = BytesIO()
? ? image.save(buf, 'jpeg')
? ? buf_str = buf.getvalue()
? ? data = str(base64.b64encode(buf_str))[1:].strip("'")? ? #將驗(yàn)證碼轉(zhuǎn)換為base64格式
? ? # session['code'] = code? #現(xiàn)在暫時(shí)未打開(kāi)朴艰,將驗(yàn)證碼文本存入session观蓄,做用戶登錄認(rèn)證時(shí)可用
? ? return data
完整的py程序?yàn)?/p>
from flask import Flask
from flask import render_template
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from io import BytesIO
import random
import base64
#驗(yàn)證碼圖片
def validate_picture():
? ? total = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345789'
? ? # 圖片大小130 x 50
? ? width = 130
? ? heighth = 50
? ? # 先生成一個(gè)新圖片對(duì)象
? ? im = Image.new('RGB',(width, heighth), 'white')
? ? # 設(shè)置字體
? ? font = ImageFont.truetype("MicrosoftYaqiHeiLight-2.ttf", 30)
? ? # 創(chuàng)建draw對(duì)象
? ? draw = ImageDraw.Draw(im)
? ? str = ''
? ? # 輸出每一個(gè)文字
? ? for item in range(4):
? ? ? ? text = random.choice(total)
? ? ? ? str += text
? ? ? ? draw.text((-3+random.randint(3,7)+25*item, -3+random.randint(2,7)), text=text, fill='black',font=font )
? ? # 劃幾根干擾線
? ? for num in range(1):
? ? ? ? x1 = random.randint(0, width/2)
? ? ? ? y1 = random.randint(0, heighth/2)
? ? ? ? x2 = random.randint(0, width)
? ? ? ? y2 = random.randint(heighth/2, heighth)
? ? ? ? draw.line(((x1, y1),(x2,y2)), fill='black', width=1)
? ? # 加上濾鏡
? ? im = im.filter(ImageFilter.FIND_EDGES)
? ? return im, str
#生成驗(yàn)證碼實(shí)例的函數(shù)
def run_code():
? ? #生成驗(yàn)證碼,image為驗(yàn)證碼圖片祠墅,code為驗(yàn)證碼文本
? ? image, code = validate_picture()
? ? # 將驗(yàn)證碼圖片以二進(jìn)制形式寫(xiě)入在內(nèi)存中侮穿,防止將圖片都放在文件夾中,占用大量磁盤(pán)
? ? buf = BytesIO()
? ? image.save(buf, 'jpeg')
? ? buf_str = buf.getvalue()
? ? data = str(base64.b64encode(buf_str))[1:].strip("'")? ? #將驗(yàn)證碼轉(zhuǎn)換為base64格式
? ? # session['code'] = code? #將驗(yàn)證碼文本存入session毁嗦,做用戶登錄認(rèn)證時(shí)可用
? ? return data
app = Flask(__name__)
@app.route('/')
def test():
? ? data = run_code()? #生成新驗(yàn)證碼?
? ? return render_template('test.html', img_stream = data) #會(huì)在下面貼出我的html源碼?
if __name__ == '__main__':
? ? ? ? app.run(host='0.0.0.0', debug=True)
二.HTML模板
Flask中創(chuàng)建如下html模板亲茅,放在 程序根目錄/templates 中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<font size="8em">
<!-- 驗(yàn)證碼顯示區(qū)域,驗(yàn)證碼以二進(jìn)制輸出到前端-->
<p class="center"><img width:"200px" src="data:;base64,{{ img_stream }}"> </p>
</font>
</body>
</html>
之后運(yùn)行Python,打開(kāi)瀏覽器輸入地址克锣,便能成功顯示驗(yàn)證碼了茵肃,每次刷新自動(dòng)生成哦
如果您有更好的方法,歡迎留言哦