利用Python生成隨機(jī)驗(yàn)證碼詳解
最近感覺(jué)被大數(shù)據(jù)定義成機(jī)器人了,隨便看個(gè)網(wǎng)頁(yè)都跳驗(yàn)證碼。

怎么用python繞驗(yàn)證碼是個(gè)令人頭禿的事情,
我投降!那么今天手把手教大家如何寫(xiě)驗(yàn)證碼,去為難別人,讓他們頭禿。
說(shuō)錯(cuò)了,其實(shí)就是教大家如何通過(guò)python代碼去生成驗(yàn)證碼~~
1.先搞環(huán)境
1.我們需要你電腦有python3.4以上的版本
2.pip安裝PIL包
pip install pillow
3.默念一遍"人生苦短,我用python",之后打開(kāi)IDLE開(kāi)始碼代碼!
2.開(kāi)始碼代碼
1. 確定畫(huà)布大小和背景色
# 導(dǎo)入相關(guān)的繪畫(huà)模塊
from PIL import Image, ImageDraw, ImageFont
# 設(shè)置背景色
bg_color = (100, 100, 255)
#設(shè)置畫(huà)布長(zhǎng)寬(像素)
width = 400
height = 100
# 通過(guò)設(shè)置生成新的畫(huà)布
im = Image.new('RGB',(width,height),bg_color)
# 展示畫(huà)布
im.show()在這 bg_color 背景色的設(shè)置是用 RGB 顏色標(biāo)準(zhǔn)去設(shè)置的,如果你不喜歡這個(gè)背景色可以自己調(diào)一下。

“常見(jiàn)的RGB顏色

運(yùn)行代碼后:

2. 往背景布上畫(huà)字符
先上代碼
from PIL import Image, ImageDraw, ImageFont
# 省略第一步的代碼
# 創(chuàng)建畫(huà)筆對(duì)象
draw = ImageDraw.Draw(im)
# 驗(yàn)證碼文本
string = 'MSBC'
# 構(gòu)造字體對(duì)象
font = ImageFont.truetype('./ziti.ttf', 90)
# font = ImageFont.load_default().font
# 構(gòu)造字體顏色
fontcolor = (255, 100, 100)
# 繪制4個(gè)字
draw.text((10, 2), string[0], font=font, fill=fontcolor)
draw.text((110, 2), string[1], font=font, fill=fontcolor)
draw.text((210, 2), string[2], font=font, fill=fontcolor)
draw.text((310, 2), string[3], font=font, fill=fontcolor)
#釋放畫(huà)筆
del draw
#展示圖片
im.show()代碼分析:
draw = ImageDraw.Draw(im)
在im畫(huà)布上實(shí)例化一只筆。
font = ImageFont.truetype('./ziti.ttf', 90)
# font = ImageFont.load_default().font
第一個(gè)參數(shù)是設(shè)置字體,我這有下載一個(gè)ttf的字體文件所以可以用它,如果沒(méi)有指定的字體文件可以使用默認(rèn)的 # font = ImageFont.load_default().font;
第二個(gè)參數(shù)是繪制字體的大小,因?yàn)槲覀儺?huà)布是400x100的 所以我們?yōu)榱嗣烙^就把字體設(shè)成90x90的尺寸。
# 構(gòu)造字體顏色 fontcolor = (255, 100, 100)
字體文本的顏色,參照第一步畫(huà)布的 RGB 設(shè)置。
# 繪制4個(gè)字 draw.text((10, 2), string[0], font=font, fill=fontcolor) draw.text((110, 2), string[1], font=font, fill=fontcolor) draw.text((210, 2), string[2], font=font, fill=fontcolor) draw.text((310, 2), string[3], font=font, fill=fontcolor)
這里 draw.text 函數(shù),顧名思義就是開(kāi)始拿畫(huà)起畫(huà)筆開(kāi)始寫(xiě)字,
第一個(gè)參數(shù) 寫(xiě)字的坐標(biāo);
第二個(gè)參數(shù) 要寫(xiě)的字;
第三個(gè)參數(shù) 字的顏色(上面構(gòu)造過(guò)了,你也可以設(shè)成一字一色)。
代碼跑一下看成果:

效果還行,就是總覺(jué)得少了點(diǎn)什么?
3. 加干擾
既然是驗(yàn)證碼,肯定要稍微難識(shí)別,上面那個(gè)那么傻白甜的驗(yàn)證碼是怎么回事??
這一步我們需要導(dǎo)入 random 模塊,因?yàn)楦蓴_是不規(guī)則隨機(jī)生成的。
import random from PIL import Image, ImageDraw, ImageFont # 省略第一步代碼 # 省略第二步代碼 #使用point函數(shù)繪制噪點(diǎn) for i in range(0, 100): ? ? xy = (random.randrange(0, width), random.randrange(0, height)) ? ? fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) ? ? draw.point(xy, fill=fill) ? ?? #釋放畫(huà)筆 del draw ?? im.show()
代碼分析:
import random
別忘了導(dǎo)入 random 模塊
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (255, 255, 255)
draw.point(xy, fill=fill)
一個(gè)循環(huán)100次的 for 循環(huán),
xy 變量是畫(huà)干擾點(diǎn)的坐標(biāo)值
fill 變量是噪點(diǎn)的顏色,還是 RGB 標(biāo)準(zhǔn)的
draw.point 畫(huà)點(diǎn)的動(dòng)作
“這個(gè)for循環(huán)的次數(shù)越多,畫(huà)布上噪點(diǎn)也會(huì)相應(yīng)增多。
跑一下代碼看看噪點(diǎn)的效果如何:

感覺(jué)還是有點(diǎn)傻白甜,我們來(lái)循環(huán)1000次的試試:

10000次!

夠了。
4. 加入更多的干擾
這一步我將各個(gè)參數(shù)結(jié)合 random 模塊,使我們的驗(yàn)證碼更難辨別!
import random
from PIL import Image, ImageDraw, ImageFont
bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
width = 400
height = 100
im = Image.new('RGB',(width,height),bg_color)
# 創(chuàng)建畫(huà)筆對(duì)象
draw = ImageDraw.Draw(im)
# 構(gòu)造字體對(duì)象
font = ImageFont.truetype('./ziti.ttf', 100)
# font = ImageFont.load_default().font
# 構(gòu)造字體顏色
fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
# 繪制4個(gè)字
string = 'MSBC'
draw.text((random.randint(10, 30), (random.randint(0, 10))), string[0], font=font, fill=fontcolor)
draw.text((random.randint(90, 130), (random.randint(0, 10))), string[1], font=font, fill=fontcolor)
draw.text((random.randint(180, 230), (random.randint(0, 10))), string[2], font=font, fill=fontcolor)
draw.text((random.randint(270, 330), (random.randint(0, 10))), string[3], font=font, fill=fontcolor)
#調(diào)用畫(huà)筆的point()函數(shù)繪制噪點(diǎn)
for i in range(0, 10000):
? ? xy = (random.randrange(0, width), random.randrange(0, height))
? ? fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
? ? draw.point(xy, fill=fill)
#釋放畫(huà)筆
del draw
im.show()我把字體顏色,噪點(diǎn)顏色,文本位置都結(jié)合了random模塊,效果圖如下:

5. 驗(yàn)證碼 + 隨機(jī)字符
這一步,我們需要把上面的代碼封裝到函數(shù)中,大致把上面代碼重構(gòu)成:
# 使用for循環(huán)生成文本字符 # 生成驗(yàn)證碼圖片的函數(shù),參數(shù)就是上面生成的文本 # 調(diào)用生成驗(yàn)證碼圖片函數(shù)
重構(gòu)后:
import random
from PIL import Image, ImageDraw, ImageFont
string = ''
#隨機(jī)選取4個(gè)值作為驗(yàn)證碼
rand_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
for i in range(0, 4):
? ? string += rand_str[random.randrange(0, len(rand_str))]
def gen_verify_img(text):
? ? bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
? ? width = 400
? ? height = 100
? ? im = Image.new('RGB',(width,height),bg_color)
? ? # 創(chuàng)建畫(huà)筆對(duì)象
? ? draw = ImageDraw.Draw(im)
? ? # 構(gòu)造字體對(duì)象
? ? font = ImageFont.truetype('./ziti.ttf', 100)
? ? # font = ImageFont.load_default().font
? ? # 構(gòu)造字體顏色
? ? fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
? ? # 繪制4個(gè)字
? ? draw.text((random.randint(10, 30), (random.randint(0, 10))), string[0], font=font, fill=fontcolor)
? ? draw.text((random.randint(90, 130), (random.randint(0, 10))), string[1], font=font, fill=fontcolor)
? ? draw.text((random.randint(180, 230), (random.randint(0, 10))), string[2], font=font, fill=fontcolor)
? ? draw.text((random.randint(270, 330), (random.randint(0, 10))), string[3], font=font, fill=fontcolor)
? ? #調(diào)用畫(huà)筆的point()函數(shù)繪制噪點(diǎn)
? ? for i in range(0, 10000):
? ? ? ? xy = (random.randrange(0, width), random.randrange(0, height))
? ? ? ? fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
? ? ? ? draw.point(xy, fill=fill)
? ? #釋放畫(huà)筆
? ? del draw
? ? im.show()
# 調(diào)用函數(shù)
gen_verify_img(string)把原先代碼中的 string 變量提到了函數(shù)外,把它變成函數(shù)需要傳入的參數(shù),
再用 for 循環(huán),隨機(jī)選出4個(gè)字符。
string = ''
#隨機(jī)選取4個(gè)值作為驗(yàn)證碼
rand_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
for i in range(0, 4):
string += rand_str[random.randrange(0, len(rand_str))]
代碼再跑一下:

上面的驗(yàn)證碼是 DZNO 還是 DZN0 ?
6. 驗(yàn)證碼保存本地(選)
在web開(kāi)發(fā)的登錄操作,和訓(xùn)練驗(yàn)證碼識(shí)別的神經(jīng)運(yùn)算中,都需要大量的驗(yàn)證碼圖片。
所以需要把大量的驗(yàn)證碼圖片文件,我們將批量驗(yàn)證碼保存到本地。

完整代碼:
import random
from PIL import Image, ImageDraw, ImageFont
def gen_verify_img(text):
? ? bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
? ? width = 400
? ? height = 100
? ? im = Image.new('RGB',(width,height),bg_color)
? ? # 創(chuàng)建畫(huà)筆對(duì)象
? ? draw = ImageDraw.Draw(im)
? ? # 構(gòu)造字體對(duì)象
? ? font = ImageFont.truetype('./ziti.ttf', 100)
? ? # font = ImageFont.load_default().font
? ? # 構(gòu)造字體顏色
? ? fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
? ? # 繪制4個(gè)字
? ? draw.text((random.randint(10, 30), (random.randint(0, 10))), string[0], font=font, fill=fontcolor)
? ? draw.text((random.randint(90, 130), (random.randint(0, 10))), string[1], font=font, fill=fontcolor)
? ? draw.text((random.randint(180, 230), (random.randint(0, 10))), string[2], font=font, fill=fontcolor)
? ? draw.text((random.randint(270, 330), (random.randint(0, 10))), string[3], font=font, fill=fontcolor)
? ? #調(diào)用畫(huà)筆的point()函數(shù)繪制噪點(diǎn)
? ? for i in range(0, 10000):
? ? ? ? xy = (random.randrange(0, width), random.randrange(0, height))
? ? ? ? fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
? ? ? ? draw.point(xy, fill=fill)
? ? #釋放畫(huà)筆
? ? del draw
? ? # im.show()
? ? im.save(f'./{text}.png','png')
for i in range(100):
? ? string = ''
? ? #隨機(jī)選取4個(gè)值作為驗(yàn)證碼
? ? rand_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
? ? for i in range(0, 4):
? ? ? ? string += rand_str[random.randrange(0, len(rand_str))]
? ? gen_verify_img(string)
? ? print(f'{string} 驗(yàn)證碼生成成功??!')最后再跑一下:

部分驗(yàn)證碼展示:

注:如果再將本文中的代碼進(jìn)行變形或改寫(xiě),可能會(huì)得到更五花八門(mén)的驗(yàn)證碼,怎么發(fā)揮就看屏幕錢(qián)你的了。
以上就是利用Python生成隨機(jī)驗(yàn)證碼詳解的詳細(xì)內(nèi)容,更多關(guān)于Python驗(yàn)證碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Python通用驗(yàn)證碼識(shí)別OCR庫(kù)ddddocr的安裝使用教程
- python自動(dòng)化測(cè)試之破解滑動(dòng)驗(yàn)證碼
- Python通用驗(yàn)證碼識(shí)別OCR庫(kù)之ddddocr驗(yàn)證碼識(shí)別
- Python實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼詳解
- Python實(shí)現(xiàn)滑塊驗(yàn)證碼詳解
- Python免費(fèi)驗(yàn)證碼識(shí)別之ddddocr識(shí)別OCR自動(dòng)庫(kù)實(shí)現(xiàn)
- python 通過(guò)SMSActivateAPI 獲取驗(yàn)證碼的步驟
相關(guān)文章
Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程
這篇文章主要介紹了Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
python unix時(shí)間戳轉(zhuǎn)換毫秒的實(shí)現(xiàn)
Unix時(shí)間戳是一種常見(jiàn)的時(shí)間表示方式,本文主要介紹了python unix時(shí)間戳轉(zhuǎn)換毫秒的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
Python實(shí)現(xiàn)讀取大量Excel文件并跨文件批量計(jì)算平均值
這篇文章主要為大家詳細(xì)介紹了如何利用Python語(yǔ)言,實(shí)現(xiàn)對(duì)多個(gè)不同Excel文件進(jìn)行數(shù)據(jù)讀取與平均值計(jì)算的方法,感興趣的可以了解一下2023-02-02
python自定義分頁(yè)器的實(shí)現(xiàn)
這篇文章主要介紹了python自定義分頁(yè)器的實(shí)現(xiàn),通過(guò)自定義分頁(yè)器封裝展開(kāi)主題并對(duì)其實(shí)用方法簡(jiǎn)單介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-04-04
python?共現(xiàn)矩陣的實(shí)現(xiàn)代碼
這篇文章主要介紹了python?共現(xiàn)矩陣的實(shí)現(xiàn)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Python 利用pandas和mysql-connector獲取Excel數(shù)據(jù)寫(xiě)入到MySQL數(shù)據(jù)庫(kù)
在實(shí)際應(yīng)用中,我們可能需要將Excel表格中的數(shù)據(jù)導(dǎo)入到MySQL數(shù)據(jù)庫(kù)中,以便于進(jìn)行進(jìn)一步的數(shù)據(jù)分析和處理,本文將介紹如何使用Python將Excel表格中的數(shù)據(jù)插入到MySQL數(shù)據(jù)庫(kù)中,需要的朋友可以參考下2023-10-10
解決Django的request.POST獲取不到內(nèi)容的問(wèn)題
今天小編就為大家分享一篇解決Django的request.POST獲取不到內(nèi)容的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05

