一、驗證碼簡介
1.什么是驗證碼
在開發(fā)爬蟲的過程中會遇到一種常見的反爬措施,驗證碼沟优。驗證碼(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自動區(qū)分計算機和人類的圖靈測試)的縮寫岔擂,是一種區(qū)分用戶是計算機還是人的公共全自動程序。
2.驗證碼種類
驗證碼自面世以來惩嘉,不斷發(fā)展罢洲,圖形驗證碼可以分為以下幾類:
字符型驗證碼:這類驗證碼大多是計算機隨機產(chǎn)生一個字符串,在把字符串增加噪點文黎、干擾線惹苗、變形、重疊耸峭、不同顏色桩蓉、扭曲組成一張圖片來增加識別難度。
-
滑動驗證碼:也叫行為驗證碼劳闹,比較流行的一種驗證碼院究,通過用戶的操作行為來完成驗證,其中最出名的就是極驗本涕。
滑動驗證碼的原理就是使用機器學(xué)習(xí)中的深度學(xué)習(xí)技術(shù)业汰,根據(jù)一些特征來區(qū)分是否為正常用戶。通過記錄用戶的滑動速度菩颖,還有每一小段時間的瞬時速度样漆,用戶鼠標點擊情況,以及滑動后的匹配程度來識別位他。而且氛濒,不是說滑動到正確位置就是驗證通過,而是根據(jù)特征識別來區(qū)分是否為真用戶鹅髓,滑到正確位置只是一個必要條件舞竿。
點觸驗證碼:點擊類驗證碼都是給出一張包含文字的圖片,通過文字提醒用戶點擊圖中相同字的位置進行驗證窿冯。
二骗奖、圖像處理庫
pillow(http://www.reibang.com/p/cd6f4e138af6
)
官方文檔:https://pillow.readthedocs.io/en/latest/installation.html
三、簡單字符串驗證碼的處理
1.灰度化
像素點是最小的圖片單元,一張圖片由很多像素點構(gòu)成执桌,一個像素點的顏色是由RGB三個值來表現(xiàn)的鄙皇,所以一個像素點對應(yīng)三個顏色向量矩陣,我們對圖像的處理就是對這個像素點的操作仰挣。
圖片的灰度化伴逸,就是讓像素點矩陣中的每一個像素點滿足 R=G=B,此時這個值叫做灰度值膘壶,白色為255错蝴,黑色為0
灰度轉(zhuǎn)化一般公式為:
R=G=B = 處理前的 RX0.3 + GX0.59 + B*0.11
from PIL import Image
image = Image.open('code.jpg')
im = image.convert('L')
2.二值化
圖像的二值化,就是將圖像的像素點矩陣中的每個像素點的灰度值設(shè)置為0(黑色)或255(白色)颓芭,從而實現(xiàn)二值化顷锰,將整個圖像呈現(xiàn)出明顯的只有黑和白的視覺效果。
二值化原理是利用設(shè)定的一個閾值來判斷圖像像素是0還是255亡问, 一般小于閾值的像素點變?yōu)?官紫, 大于的變成255。
這個臨界灰度值就被稱為閾值州藕,閾值的設(shè)置很重要束世,閾值過大或過小都會對圖片造成損壞。
選擇閾值的原則是:既要盡可能保存圖片信息慎框,又要盡可能減少背景和噪聲的干擾良狈。
二值化的優(yōu)點:進一步的減小數(shù)據(jù)量后添,盡可能保存圖片的信息笨枯,盡可能的減少背景的噪聲干擾。
常用閾值選擇的方法是:
?----灰度平局值法: 取127 (0~255的中數(shù)遇西, (0+255)/2 = 127)
平均值法:
? ----計算像素點矩陣中的所有像素點的灰度值的平均值avg
-----迭代法: 選擇一個近似閾值作為估計值的初始值馅精,然后進行分割圖像,根據(jù)產(chǎn)生的子圖像的特征來選取新的閾值粱檀,在利用新的閾值分割圖像洲敢,經(jīng)過多次循環(huán),使得錯誤分割的圖像像素點降到最小茄蚯。
from PIL import Image
def to_value(img):
# 獲取尺寸
w, h = img.size
print('這個寬為%s,高為%s' % (w, h))
# 獲取像素
pixes = img.load()
total = []
for i in range(w):
for j in range(h):
total.append(pixes[i, j])
print(total)
# 計算平均值
avg = sum(total)//len(total)
#進行二值化處理(使圖像顯示出來要么是白色压彭,要么是黑色)
for i in range(w):
for j in range(h):
if pixes[i, j] < avg:
pixes[i, j] = 0
else:
pixes[i, j] = 255
# return img.point(lambda x: 0 if x < avg else 255)返回一個新的img對象
img = Image.open('genimage.png')
# # 增強對比度
img = img.point(lambda x: 1.2*x)
# 進行圖像灰度化處理
img = img.convert('L')
to_value(img)
img.show()
3.降噪
經(jīng)過了二值化處理,整個圖片像素就被分為了兩個值0和255渗常, 如果一個像素點是圖片或者干擾因素的一部分壮不,那么她的灰度值一定是0(黑色),如果一個點是背景皱碘,其灰度值應(yīng)該是255(白色)询一。
所以對于孤立的噪點,他的周圍應(yīng)該都是白色,或者大多數(shù)點都是白色的健蕊,所以在判斷的時候條件應(yīng)該放寬菱阵,一個點是黑色并且相鄰的點為白色的點的個數(shù)大于一個固定的值,那么這個點就是噪點缩功。
from PIL import Image
def noise_reduction(img):
w, h = img.size
pixes = img.load()
# 先處理4條邊
# 頂邊
for i in range(w):
if pixes[i,0] == 0:
if pixes[i, 1] == 255:
pixes[i, 0] = 255
# 底邊
for i in range(w):
if pixes[i,h-1] == 0:
if pixes[i, h-2] == 255:
pixes[i, h-1] = 255
# 左邊
for i in range(h):
if pixes[0, i] == 0:
if [1, i] == 255:
pixes[0, i] = 255
# 右邊
for i in range(h):
if pixes[w-1, i] == 0:
if [w-2, i] == 255:
pixes[w-1, i] = 255
# 處理其他的點
for i in range(1, w-1):
for j in range(1, h-1):
if pixes[i, j] == 0:
sum = pixes[i+1, j] + pixes[i, j+1] + pixes[i-1, j] + pixes[i, j-1] + pixes[i-1, j-1] + pixes[i+1, j-1] + pixes[i+1, j+1] + pixes[i-1, j+1]
if sum // 255 > 4:
pixes[i, j] = 255
return img
四晴及、識別
字符識別可使用谷歌開源項目------Tesseract OCR
。
1.工具安裝
1.1Tesseract OCR引擎安裝
github地址:https://github.com/tesseract-ocr/tesseract/wiki
-
windows
ubuntu安裝
1.2 Python Tesseract安裝
Python -Tesseract是一種用于Python的光學(xué)字符識別(OCR)工具嫡锌。也就是說抗俄,它將識別和“讀取”圖像中嵌入的文本。Python-tesseract是對谷歌Tesseract OCR
引擎的python封裝世舰。它還可用作Tesseract的獨立調(diào)用腳本动雹,因為它可以讀取Pillow和Leptonica圖像庫支持的所有圖像類型,包括jpeg跟压、png胰蝠、gif、bmp震蒋、tiff等茸塞。
官方文檔:https://github.com/madmaze/pytesseract
安裝:
pip install pytesseract
簡單使用:
try:
from PIL import Image
except ImportError:
import Image
import pytesseract
# If you don't have tesseract executable in your PATH, include the following:
pytesseract.pytesseract.tesseract_cmd = r'<full_path_to_your_tesseract_executable>'
# Example tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract'
# Simple image to string
print(pytesseract.image_to_string(Image.open('test.png')))
# French text image to string
print(pytesseract.image_to_string(Image.open('test-european.jpg'), lang='fra'))