這週一寫了一篇《2000字諫言,給那些想學Python的人,建議收藏後細看!》給你們講了如何快速學習python。python
其中就有說到咱們爲何不要執迷於框架、模塊的調用,而要本身先去造輪子。那今天就給你們造一個。git
驗證碼是web開發中不可缺乏的元素,而python又提供了很是多的驗證碼模塊幫助你們快速生成各類驗證碼。github
那你知道驗證碼生成的原理嗎?所謂知其然,還要知其因此然。面試中,面試官不會由於你對框架很熟悉就誇讚你。web
那今天小胖就帶你們一層一層撥開驗證碼的衣服,看看其中的小奧祕 -<-面試
咱們既然須要使用pillow庫製做驗證碼,那麼首先咱們先來熟悉一下咱們須要用到的方法。windows
'RGBA','RGB','L'
等等模式red,green
等,也能夠是rgb的三個整數的元祖。也就是背景顏色from PIL import Image
captcha = Image.new('RGB', (1080, 900), (255,255,255))
複製代碼
上面代碼建立了一個億RGB爲顏色空間模式,尺寸爲1080*900,背景顏色爲白色的圖片。框架
from PIL import Image
captcha = Image.new('RGB', (1080, 900), (255,255,255))
# captcha.save('captcha.png')
captcha.save('captcha', format='png')
複製代碼
上面兩種方式保存效果是同樣的。dom
Image.show():顯示圖片,會調用電腦自帶的顯示圖片的軟件。機器學習
ImageFont.truetype(): 加載一個字體文件。生成一個字體對象。編輯器
from PIL import ImageFont
# 字體文件路徑 字體大小
font = ImageFont.truetype('simkai.ttf', 16)
複製代碼
from PIL import Image, ImageDraw
captcha = Image.new('RGB', (1080, 900), 'red')
draw = ImageDraw.Draw(captcha)
複製代碼
上面就建立了一個在captcha這張圖片上的畫筆,咱們在這個圖片上畫任何東西都會使用這個畫筆對象。
from PIL import Image, ImageDraw, ImageFont
captcha = Image.new('RGB', (1080, 900), 'red')
font = ImageFont.truetype('simkai.ttf', 16)
draw = ImageDraw.Draw(captcha)
# 字符繪製位置 繪製的字符 制定字體 字符顏色
draw.text((0,0), 'hello world', font=font, fill='black')
複製代碼
from PIL import Image, ImageDraw, ImageFont
captcha = Image.new('RGB', (1080, 900), 'red')
draw = ImageDraw.Draw(captcha)
# 線條起點 線條終點
draw.line([(0,0),(1080,900)], fill='black')
複製代碼
from PIL import Image, ImageDraw, ImageFont
captcha = Image.new('RGB', (1080, 900), 'red')
font = ImageFont.truetype('simkai.ttf', 16)
draw = ImageDraw.Draw(captcha)
# 點的位置 顏色
draw.point((500,500), fill='black')
複製代碼
製做咱們的驗證碼咱們就會使用到上面的方法。固然,pillow確定不止這些方法,這裏咱們就只列舉這些了。
import string
class Captcha():
''' captcha_size: 驗證碼圖片尺寸 font_size: 字體大小 text_number: 驗證碼中字符個數 line_number: 線條個數 background_color: 驗證碼的背景顏色 sources: 取樣字符集。驗證碼中的字符就是隨機從這個裏面選取的 save_format: 驗證碼保存格式 '''
def __init__(self, captcha_size=(150,100), font_size=30,text_number=4, line_number=4, background_color=(255, 255, 255), sources=None, save_format='png'):
self.text_number = text_number
self.line_number = line_number
self.captcha_size = captcha_size
self.background_color = background_color
self.font_size = font_size
self.format = save_format
if sources:
self.sources = sources
else:
self.sources = string.ascii_letters + string.digits
複製代碼
這裏說一下string模塊。
import random
def get_text(self):
text = random.sample(self.sources,k=self.text_number)
return ''.join(text)
複製代碼
random.sample()方法:從第一個參數中隨機獲取字符。獲取個數有第二個參數指定。
def get_font_color(self):
font_color = (random.randint(0, 150), random.randint(0, 150), random.randint(0, 150))
return font_color
複製代碼
def get_line_color(self):
line_color = (random.randint(0, 250), random.randint(0, 255), random.randint(0, 250))
return line_color
複製代碼
def draw_text(self,draw, text, font, captcha_width, captcha_height, spacing=20):
''' 在圖片上繪製傳入的字符 :param draw: 畫筆對象 :param text: 繪製的全部字符 :param font: 字體對象 :param captcha_width: 驗證碼的寬度 :param captcha_height: 驗證碼的高度 :param spacing: 每一個字符的間隙 :return: '''
# 獲得這一竄字符的高度和寬度
text_width, text_height = font.getsize(text)
# 獲得每一個字體的大概寬度
every_value_width = int(text_width / 4)
# 這一竄字符的總長度
text_length = len(text)
# 每兩個字符之間擁有間隙,獲取總的間隙
total_spacing = (text_length-1) * spacing
if total_spacing + text_width >= captcha_width:
raise ValueError("字體加中間空隙超過圖片寬度!")
# 獲取第一個字符繪製位置
start_width = int( (captcha_width - text_width - total_spacing) / 2 )
start_height = int( (captcha_height - text_height) / 2 )
# 依次繪製每一個字符
for value in text:
position = start_width, start_height
print(position)
# 繪製text
draw.text(position, value, font=font, fill=self.get_font_color())
# 改變下一個字符的開始繪製位置
start_width = start_width + every_value_width + spacing
複製代碼
def draw_line(self, draw, captcha_width, captcha_height):
''' 繪製線條 :param draw: 畫筆對象 :param captcha_width: 驗證碼的寬度 :param captcha_height: 驗證碼的高度 :return: '''
# 隨機獲取開始位置的座標
begin = (random.randint(0,captcha_width/2), random.randint(0, captcha_height))
# 隨機獲取結束位置的座標
end = (random.randint(captcha_width/2,captcha_width), random.randint(0, captcha_height))
draw.line([begin, end], fill=self.get_line_color())
複製代碼
def draw_point(self, draw, point_chance, width, height):
''' 繪製小圓點 :param draw: 畫筆對象 :param point_chance: 繪製小圓點的概率 機率爲 point_chance/100 :param width: 驗證碼寬度 :param height: 驗證碼高度 :return: '''
# 按照機率隨機繪製小圓點
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp < point_chance:
draw.point((w, h), fill=self.get_line_color())
複製代碼
def make_captcha(self):
# 獲取驗證碼的寬度, 高度
width, height = self.captcha_size
# 生成一張圖片
captcha = Image.new('RGB',self.captcha_size,self.background_color)
# 獲取字體對象
font = ImageFont.truetype('simkai.ttf',self.font_size)
# 獲取畫筆對象
draw = ImageDraw.Draw(captcha)
# 獲得繪製的字符
text = self.get_text(
# 繪製字符
self.draw_text(draw, text, font, width, height)
# 繪製線條
for i in range(self.line_number):
self.draw_line(draw, width, height)
# 繪製小圓點 10是機率 10/100, 10%的機率
self.draw_point(draw,10,width,height)
# 保存圖片
captcha.save('captcha',format=self.format)
# 顯示圖片
captcha.show()
複製代碼
這樣,咱們就生成了咱們的圖片驗證碼了,效果圖.
代碼已所有上傳至Github:github.com/MiracleYoun…
關注公衆號「Python專欄」,後臺回覆「機器學習電子書」獲取100本免費機器學習相關的電子書哦~