寫爬蟲有一個繞不過去的問題,那就是驗證碼,好比像某乎,若是不先登錄,連裏面的內容數據都爬不到,而驗證碼就是網站進行發爬蟲的一種措施,隨着技術的發展,驗證碼愈來愈複雜,爬蟲的工做愈來愈艱苦,因此此次就來說解,怎麼來識別驗證碼;(聽上去口氣很大的感受)
php
1)圖形驗證碼
圖形驗證碼應該是最簡單的一種驗證碼,這種驗證碼是最先出現,也是目前最多見的,通常組成規則是4個字母或數字或混合組成; git
2)滑動驗證碼
github
3)點觸驗證碼
windows
Ok,上面這3種驗證碼方式,應該是目前PC上比較常見的驗證碼種類的,固然手機app上還會有手勢驗證,宮格驗證,語音驗證等等,這裏就不介紹,主要針對上面常見的3種介紹;服務器
某乎的驗證碼有2種,一種是圖形驗證碼,一種是點觸驗證碼,通過測試發現,一開始是顯示圖形驗證碼,但當登錄退出次數逐漸增多,就會變成點觸驗證碼,這種驗證碼的切換機制,也算是防爬蟲的一種手段,閒話很少說,先喵喵:
app
某乎連接:https://www.zhihu.com/signup?next=%2F
打開後默認是在註冊頁面,點擊下登錄按鈕,若是仍是沒有驗證碼,刷新幾回網頁就好了; scrapy
下面這種,下2篇文章會介紹; 工具
識別圖形驗證碼須要安裝tesserocr這個庫,下面介紹下tesserocr;
tesserocr是Python的一個OCR識別庫,但實際上是對tesseract作了一層Python Api的封裝,
核心仍是tesseract,因此在安裝tesserocr以前,須要先安裝tesseract;post
等下,懵逼中,tesserocr這個能看明白,是一個庫,但OCR是什麼?tesseract又是什麼?
學習
OCR
OCR,全稱叫 Optical Character Recognition,中文翻譯叫光學字符識別,是指經過掃描字符,經過其形狀將其翻譯成電子文本的過程;
舉例:
當有一個圖形驗證碼,先使用OCR技術將其轉化成電子文本,而後爬蟲將識別的結果提交到服務器,便達到自動識別驗證碼的過程;
tesseract
tesseract是google開源的OCR
OK,貌似對概念有所理解了,還有個疑問,以前有在圖形識別領域,還有個opencv的玩意,那這二者有什麼區別?
opencv專一機器視覺
tesseract專一字符識別
因此從領域來講,opencv更廣,而圖形驗證碼,opencv也能夠作,但殺雞焉用牛刀~
windows下的安裝
在Windows下,要先下載tesseract,它爲tesserocr提供了支持;
tesseract下載地址:https://digi.bib.uni-mannheim.de/tesseract/
打開後,能夠看到各類exe的列表,能夠隨便挑選;
其中文件名中帶有dev的爲開發版本,不帶dev則爲穩定版本,例如jb是下載 tesseract-ocr-setup-3.05.01.exe;
下載後雙擊,一路點擊,直到出現下面這個頁面
這裏須要勾選紅框裏的Additional language data(download),這個選項是安裝OCR識別支持的語言包,這樣OCR就能夠識別多國語言,而後再一路點擊NEXT便可,由於要下載語言包,因此須要點時間,大概10-20分鐘左右,跟網速有關,若是不須要支持多國語言的話,也能夠不勾選,自由選擇
須要說明:默認包含英文字庫
若是,以爲一次下載那麼多語言佔空間,又或者以爲網速慢,也能夠選擇單獨安裝中文字庫;
字庫下載地址:https://github.com/tesseract-ocr/tessdata
打開後,直接搜索chi_sim.traineddata,這個表明的就是中文,下載下來;
而後找到剛剛tesseract安裝目錄,裏面會有一個叫tessdata的目錄,直接把剛下載的語言包放到這個目錄下便可;
如何驗證tesseract是否安裝成功?直接cmd下輸入tesseract便可;
成功會直接顯示信息;
若是提示'tesseract' 不是內部或外部命令,則是由於沒有配置環境變量,手動把tesseract根目錄配置到path參數下便可,這塊不詳細說明;
到此爲止,tesseract安裝成功啦~
接下來就安裝tesserocr,直接pip命令便可:
pip3 install tesserocr install
複製代碼
但jb在安裝的時候,直接報錯:
試過不少種方式,就算使用conda install tesserocr,也同樣報錯。
經歷千辛萬苦,終於找到一條可行的命令:
conda install -c simonflueckiger tesserocr
複製代碼
最終就安裝上tesserocr啦~
如何驗證是否真的安裝了?很簡單,直接import tesserocr,不報錯就說明安裝好了;
對了,若是有同窗不知道conda這條命令的話,請訪問下面的連接,直接搜索scrapy安裝,會有介紹conda:
https://juejin.im/post/5afcb91251882565bd257097|
OK,windows下的tesserocr跟tesseract的環境已經安裝好了;
彆着急,順便介紹下Linux跟Mac,但如下方式均未通過jb驗證,信息來源於網上,僅供參考:
Linux下的安裝
對於Liunx來講,不一樣系統已經有了不一樣的發行包了,它可能叫作tesseract-ocr或者tesseract,直接用對應的命令安裝便可;
Ubuntu、Debian和Deepin
在Ubuntu、Debian和Deepin系統下,安裝命令以下:
sudo apt-get install-y tesseract-ocr libtesseract-dev libleptioica-dev
複製代碼
CentOS、Red Hat 在CentOS和Red Hat系統下,安裝命令以下:
yum install -y tesseract
複製代碼
在不一樣發行版本運行如上命令,便可完成tesseract的安裝;
安裝完成後,即可以調用tesseract命令;
默認也是指安裝英文語言,若是須要安裝其餘語言,請看下上面Windows的介紹,同樣的處理方案,這裏不重複說明;
接下來就是安裝tesserocr,直接使用pip安裝:
pip3 install tesserocr pillow
複製代碼
Mac下的安裝
在Mac下,首先使用Homebrew 安裝ImageMagick 和tesseract庫:
brew install imagemagick
brew install tesseract --all-languages
複製代碼
接下來再安裝tesserocr便可:
brew install tesserocr pillow
複製代碼
爲了方便測試,須要把驗證碼的圖片保存到本地;
打開weibo.com,隨便輸入帳號密碼,會提示輸入驗證碼,打開開發者工具,找到驗證碼元素,它的src屬性就是一個連接,copy出來直接打開,會看到一個驗證碼,並且刷新的驗證碼會變化,由此推斷這是個驗證碼的接口,右鍵保存驗證碼便可,就獲得一張驗證碼;
驗證碼連接:
https://login.sina.com.cn/cgi/pin.php?r=9967937&s=0&p=gz-d0dc363f6a4523cbd602a5a10f00c59b4784
ok,完事具有,那就開始吧,新建項目,把驗證碼放到項目根目錄下;
用tesserocr庫來識別驗證碼:
import tesserocr
from PIL import Image
#新建Image對象
image = Image.open("3.jpg")
#調用tesserocr的image_to_text()方法,傳入image對象完成識別
result = tesserocr.image_to_text(image)
print(result)
複製代碼
結果,運行後,啥都沒有???
接下來jb陷入了困擾,包括調試,找各類文檔,最終,把上面調試的驗證碼換了一個:
替換下圖片,再執行一次代碼:
目前兩個問題:
1)微博的驗證碼識別失敗,輸出空
2)第二章驗證碼部分詞識別有誤
心想,這庫是網上都推薦用的,是Google開源的,理論上沒問題,並且人家也都這麼用,爲何這裏就有問題?難道還須要額外的處理?
懷着疑問跟夢想,繼續學習;
題外話: tesserocr還有一個更加簡單的方法,這個方法可直接將圖片文件轉換成字符串,代碼以下:
import tesserocr
print(tesserocr.file_to_text("1.jpg"))
複製代碼
關於微博驗證碼爲空,使用tesseract輸出下緣由:
tesseract 圖片路徑 output
複製代碼
網上找了下信息,好比這張驗證碼:
多是驗證碼內的多餘線條幹擾了圖片的識別;
又好比微博這張:
解決方案仍是有的,須要對圖片進行額外的處理,如轉灰度,二值化等操做;
轉灰度處理: 利用Image對象的convert()方法參數傳入L,便可將圖片轉成爲灰度圖像:
from PIL import Image
image = Image.open("1.jpg")
image = image.convert('L')
image.show()
複製代碼
傳入1的後,便可將圖片進行二值化處理:
(二值化是指將圖像上的像素點的灰度值設置爲0或255,也就是將整個圖片呈現出明顯的只有黑和百的視覺效果)
import tesserocr
from PIL import Image
image = Image.open("1.jpg")
image = image.convert('1')
image.show()
複製代碼
二值化的閾值是能夠指定的,上面的方法採用的是默認閾值127;但通常不多直接轉換原圖,緣由如上可看到,錯誤的更加離譜了;
通常是先將原圖轉爲灰度圖像,而後再指定二值化的閾值,代碼以下:
import tesserocr
from PIL import Image
#新建Image對象
image = Image.open("1.jpg")
#進行置灰處理
image = image.convert('L')
#這個是二值化閾值
threshold = 150
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
#經過表格轉換成二進制圖片,1的做用是白色,否則就所有黑色了
image = image.point(table,"1")
image.show()
result = tesserocr.image_to_text(image)
print(result)
複製代碼
這裏說明下,可能有同窗對256不明白,這是什麼?
首先,咱們是把圖片置灰處理,灰度圖像是一種具備從黑到白256級灰度色階或等級的單色圖像;
對於灰度圖像利用閾值獲得二值化的圖像, 也就是說,咱們設定了一個閾值,從0到256,若是灰度圖像少於閾值則設置0,大於閾值則設置1,0是黑色,1是白色,這樣作,就能夠把一個灰度圖徹底轉換二值化圖;
可能仍是懵逼,直接貼圖:
原圖
灰度圖:
二值圖:
在灰度圖上,部分色彩是介於白色跟黑色之間,因此經過設置閾值的方法,把這些中間色彩所有轉換成黑色跟白色;
ok,扯遠了,上面把驗證碼二值圖後是長這樣的:
而校驗結果:
good,有所變化, 至少不是MEEE了,那咱們繼續調,調到一個合適的值;
調了半天,jb放棄了,緣由是這個8,無論怎麼調都調不到一個合適的值,一直在S、R、B之間徘徊;
JB換了個驗證碼:
上面一樣的代碼,無修改,二值圖以下:
校驗結果:
oh year,這個能校驗出來了~
還記得咱們一開始那個微博驗證碼嗎?咱們也來試試,處理後的驗證碼是這樣的~
對比了下,微博驗證碼跟上面能識別的驗證碼:
更新於18.6.11
忽然想起,上面安裝的時候有說起到安裝不一樣語言包,那若是要看看其餘語言,怎麼搞?所以就補充這點了~
先上圖~
直接上代碼:
import tesserocr
from PIL import Image
image = Image.open("juejin.jpg")
result = tesserocr.image_to_text(image, lang='chi_sim')
print(result)
複製代碼
由於默認是英文,因此英文不須要指定lang,但中文就須要啦,chi_sim就是簡體中文了;
從輸出的結果來看,小冊那估計有個sale,否則估計開源庫也能匹配出來~
但依然能夠看出,中文也不是很精準~
這裏說明下,中午不須要置灰跟二值哈,否則顏色加深了,估計更難辨別了~
本章學習了tesserocr及tesseract的環境搭建,以及如何對圖形驗證碼進行噪音處理,而且講解灰色圖跟二值圖的概念;
實際發現,tesserocr僅能解決實心的驗證碼,對於空心的驗證碼,依然一籌莫展,那怎麼辦呢?
既然圖像識別存在偏差,那咱們就放棄這條路,而是經過其餘的方式來獲取這個驗證碼;
好比直接找到生成這驗證碼的代碼二次轉化獲取驗證碼,深度學習訓練機器識別;
下章預告:
如何獲取驗證碼的生成代碼二次處理獲取驗證碼
18.6.11更新 上面的話題,留到下下章處理,下章介紹下收費的OCR~
謝謝你們~