許多網(wǎng)站在注冊(cè)時(shí)都要求輸入驗(yàn)證碼,這樣做為了防止被程序惡意注冊(cè)和保證網(wǎng)站安全
1. Pillow
PIL(Python Imaging Library)
是一個(gè)強(qiáng)大的python圖像處理庫(kù),只是支持到python2.7
, Pillow雖說(shuō)是PIL的一個(gè)分支,但是pillow支持python3.x,已經(jīng)發(fā)展成比PIL本身更具活力的圖像處理庫(kù),我們使用Pillow來(lái)生成驗(yàn)證碼,安裝方式為
pip install Pillow
2. 生成一張指定大小隨機(jī)顏色的圖片
2.1 隨機(jī)顏色
顏色的處理使用(r,g,b)格式,r, g, b 的范圍是[0, 255], 使用random
模塊的randint
方法生成3個(gè)隨機(jī)數(shù)
def random_color():
c1 = random.randint(0, 255)
c2 = random.randint(0, 255)
c3 = random.randint(0, 255)
return c1, c2, c3
2.2 生成一張指定大小的圖片
def random_color():
c1 = random.randint(0, 255)
c2 = random.randint(0, 255)
c3 = random.randint(0, 255)
return c1, c2, c3
def generate_picture(width=120, height=35):
image = Image.new('RGB', (width, height), random_color())
return image
if __name__ == '__main__':
image = generate_picture()
image.save('test.png')
現(xiàn)在還只是生成了一張顏色隨機(jī)的圖片,接下來(lái)要在圖片上面寫(xiě)上隨機(jī)數(shù)字和字母
3. 在圖片上寫(xiě)上隨機(jī)數(shù)字和字母
3.1 生成隨機(jī)數(shù)字和字母
def get_random_str():
'''
獲取一個(gè)隨機(jī)字符, 數(shù)字或小寫(xiě)字母
:return:
'''
random_num = str(random.randint(0, 9))
random_low_alpha = chr(random.randint(97, 122))
random_char = random.choice([random_num, random_low_alpha])
return random_char
使用random模塊提供的隨機(jī)函數(shù)生成指定長(zhǎng)度的字符串
3.2 在image對(duì)象上畫(huà)數(shù)字和字母
def draw_str(count, image, font_size):
"""
在圖片上寫(xiě)隨機(jī)字符
:param count: 字符數(shù)量
:param image: 圖片對(duì)象
:param font_size: 字體大小
:return:
"""
draw = ImageDraw.Draw(image)
# 獲取一個(gè)font字體對(duì)象參數(shù)是ttf的字體文件的目錄,以及字體的大小
font_file = os.path.join('Andale Mono.ttf')
font = ImageFont.truetype(font_file, size=font_size)
temp = []
for i in range(count):
random_char = random_str()
draw.text((10+i*30, -2), random_char, random_color(), font=font)
temp.append(random_char)
valid_str = "".join(temp) # 驗(yàn)證碼
return valid_str, image
if __name__ == '__main__':
image = generate_picture()
valid_str, image = draw_str(4, image, 35)
image.save('test.png')
創(chuàng)建一個(gè)ImageDraw.Draw
對(duì)象,在image上畫(huà)隨機(jī)字符,你可以設(shè)置字體, 我使用了Andale Mono.ttf
, mac電腦上在/System/Library/Fonts
目錄下找到字體,其他系統(tǒng)也有各自的字體文件,將字體文件復(fù)制到與腳本相同的目錄下。
4. 制造噪點(diǎn)
為了防止驗(yàn)證碼被輕易的破解,還應(yīng)該在圖片上制造一些噪點(diǎn),隨機(jī)畫(huà)幾條線,隨機(jī)畫(huà)幾個(gè)點(diǎn)
def noise(image, width=120, height=35, line_count=3, point_count=20):
'''
:param image: 圖片對(duì)象
:param width: 圖片寬度
:param height: 圖片高度
:param line_count: 線條數(shù)量
:param point_count: 點(diǎn)的數(shù)量
:return:
'''
draw = ImageDraw.Draw(image)
for i in range(line_count):
x1 = random.randint(0, width)
x2 = random.randint(0, width)
y1 = random.randint(0, height)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=random_color())
# 畫(huà)點(diǎn)
for i in range(point_count):
draw.point([random.randint(0, width), random.randint(0, height)], fill=random_color())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=random_color())
return image
if __name__ == '__main__':
image = generate_picture()
valid_str, image = draw_str(4, image, 35)
image = noise(image)
image.save('test.png')
5. 生成base64編碼的圖片
實(shí)踐中,如果是生成網(wǎng)站注冊(cè)使用的驗(yàn)證碼圖片,一般來(lái)說(shuō)不會(huì)將其保存到圖片文件中,因?yàn)檫@會(huì)生成大量的小圖片,完全沒(méi)必要。我們可以將圖片的內(nèi)容保存到BytesIO
對(duì)象中,最終生成base64
編碼的圖片,這樣,向前端傳回去的就是字符串,格式為
data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAH...
data:image/jpeg;base64
這一段是固定寫(xiě)法,逗號(hào)剩余的部分是圖片經(jīng)過(guò)base64編碼后的字符串文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-690593.html
def valid_code():
"""
生成圖片驗(yàn)證碼,并對(duì)圖片進(jìn)行base64編碼
:return:
"""
image = generate_picture()
valid_str, image = draw_str(4, image, 35)
image = noise(image)
f = BytesIO()
image.save(f, 'png') # 保存到BytesIO對(duì)象中, 格式為png
data = f.getvalue()
f.close()
encode_data = base64.b64encode(data)
data = str(encode_data, encoding='utf-8')
img_data = "data:image/jpeg;base64,{data}".format(data=data)
return valid_str, img_data
if __name__ == '__main__':
print(valid_code())
6. 全部代碼
為了向你闡述生成驗(yàn)證碼圖片的過(guò)程,我將整個(gè)過(guò)程進(jìn)行拆解,因此代碼也被拆解的凌亂,你可以將這些代碼整合,以便在實(shí)際應(yīng)用中使用文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-690593.html
import os
import random
import base64
from io import BytesIO
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
def random_color():
c1 = random.randint(0, 255)
c2 = random.randint(0, 255)
c3 = random.randint(0, 255)
return c1, c2, c3
def generate_picture(width=120, height=35):
image = Image.new('RGB', (width, height), random_color())
return image
def random_str():
'''
獲取一個(gè)隨機(jī)字符, 數(shù)字或小寫(xiě)字母
:return:
'''
random_num = str(random.randint(0, 9))
random_low_alpha = chr(random.randint(97, 122))
random_char = random.choice([random_num, random_low_alpha])
return random_char
def draw_str(count, image, font_size):
"""
在圖片上寫(xiě)隨機(jī)字符
:param count: 字符數(shù)量
:param image: 圖片對(duì)象
:param font_size: 字體大小
:return:
"""
draw = ImageDraw.Draw(image)
# 獲取一個(gè)font字體對(duì)象參數(shù)是ttf的字體文件的目錄,以及字體的大小
font_file = os.path.join('Andale Mono.ttf')
font = ImageFont.truetype(font_file, size=font_size)
temp = []
for i in range(count):
random_char = random_str()
draw.text((10+i*30, -2), random_char, random_color(), font=font)
temp.append(random_char)
valid_str = "".join(temp) # 驗(yàn)證碼
return valid_str, image
def noise(image, width=120, height=35, line_count=3, point_count=20):
'''
:param image: 圖片對(duì)象
:param width: 圖片寬度
:param height: 圖片高度
:param line_count: 線條數(shù)量
:param point_count: 點(diǎn)的數(shù)量
:return:
'''
draw = ImageDraw.Draw(image)
for i in range(line_count):
x1 = random.randint(0, width)
x2 = random.randint(0, width)
y1 = random.randint(0, height)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=random_color())
# 畫(huà)點(diǎn)
for i in range(point_count):
draw.point([random.randint(0, width), random.randint(0, height)], fill=random_color())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=random_color())
return image
def valid_code():
"""
生成圖片驗(yàn)證碼,并對(duì)圖片進(jìn)行base64編碼
:return:
"""
image = generate_picture()
valid_str, image = draw_str(4, image, 35)
image = noise(image)
f = BytesIO()
image.save(f, 'png') # 保存到BytesIO對(duì)象中, 格式為png
data = f.getvalue()
f.close()
encode_data = base64.b64encode(data)
data = str(encode_data, encoding='utf-8')
img_data = "data:image/jpeg;base64,{data}".format(data=data)
return valid_str, img_data
if __name__ == '__main__':
print(valid_code())
到了這里,關(guān)于使用python,生成數(shù)字在圖片上的驗(yàn)證碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!