今天要給你們介紹的是驗證碼的爬取和識別,不過只涉及到最簡單的圖形驗證碼,也是如今比較常見的一種類型。html
運行平臺:Windowsjava
Python版本:Python3.6python
IDE: Sublime Text數組
其餘:Chrome瀏覽器瀏覽器
簡述流程多線程
步驟1:簡單介紹驗證碼app
步驟2:爬取少許驗證碼圖片測試
步驟3:介紹百度文字識別OCR字體
步驟4:識別爬取的驗證碼優化
步驟5:簡單圖像處理
目前,不少網站會採起各類各樣的措施來反爬蟲,驗證碼就是其中一種,好比當檢測到訪問頻率太高時會彈出驗證碼讓你輸入,確認訪問網站的不是機器人。但隨着爬蟲技術的發展,驗證碼的花樣也愈來愈多,從最開始簡單的幾個數字或字母構成的圖形驗證碼(也就是咱們今天要涉及的)發展到須要點擊倒立文字字母的、與文字相符合的圖片的點觸型驗證碼,須要滑動到合適位置的極驗滑動驗證碼,以及計算題驗證碼等等,總之花樣百出,讓人頭禿。驗證碼其餘的相關知識你們能夠看下這個網站:captcha.org
再來簡單說下圖形驗證碼吧,就像這張:
由字母和數字組成,再加上一些噪點,但爲了防止被識別,簡單的圖形驗證碼如今也變得複雜,有的加了干擾線,有的加噪點,有的加上背景,字體扭曲、粘連、鏤空、混用等等,甚至有時候人眼都難以識別,只能默默點擊「看不清,再來一張」。
驗證碼難度的提升隨之帶來的就是識別的成本也須要提升,在接下來的識別過程當中,我會先直接使用百度文字識別OCR,來測試識別準確度,再確認是否選擇轉灰度、二值化以及去幹擾等圖像操做優化識別率。
接下來咱們就來爬取少許驗證碼圖片存入文件。
首先打開Chrome瀏覽器,訪問剛剛介紹的網站,裏面有一個captcha圖像樣本連接:https://captcha.com/captcha-examples.html?cst=corg,網頁裏有60張不一樣類型的圖形驗證碼,足夠咱們用來識別試驗了。
直接來看代碼吧:
仍然使用Xpath爬取,在右鍵檢查圖片時能夠發現,網頁分爲兩欄,以下圖紅框所示,根據class分爲左右兩欄,驗證碼分別位於兩欄中。
這裏我使用了Xpath中的路徑選擇,在路徑表達式中使用「|」表示選取若干路徑,例如這裏表示的就是選取class爲"captcha_images_left"或者"captcha_images_right"的區塊。再來看下運行結果:
因爲每爬取一張驗證碼圖片都強制等待了1秒,最後這個運行時間確實讓人絕望,看樣子仍是須要多線程來加快速度的,關於多進程多線程咱們下次再說,這裏咱們先來看下爬取到的驗證碼圖片。
圖片到手了,接下來就是調用百度文字識別的OCR來識別這些圖片了,在識別以前,先簡單介紹一下百度OCR的使用方法,由於不少識別驗證碼的教程用的都是tesserocr庫,因此一開始我也嘗試過,安裝過程當中就遇到了不少坑,後來仍是沒有繼續使用,而是選擇了百度OCR來識別。百度OCR接口提供了天然場景下圖片文字檢測、定位、識別等功能。文字識別的結果能夠用於翻譯、搜索、驗證碼等代替用戶輸入的場景。另外還有其餘視覺、語音技術方面的識別功能,你們能夠直接閱讀文檔瞭解:百度OCR-API文檔
https://ai.baidu.com/docs#/OCR-API/top
使用百度OCR的話,首先註冊用戶,而後下載安裝接口模塊,直接終端輸入pip install baidu-aip便可。而後建立文字識別應用,獲取相關Appid,API Key以及Secret Key,須要瞭解一下的是百度AI每日提供50000次免費調用通用文字識別接口的使用次數,足夠咱們揮霍了。
而後就能夠直接調用代碼了。
這裏咱們識別的是這張圖
能夠看一下識別結果
上面是識別後直接輸出的結果,下面是單獨提取出來的文字部分。能夠看到,除了破折號沒有輸出外,文字部分都所有正確輸出了。這裏咱們使用的圖片是jpg格式,文字識別傳入的圖像支持jpg/png/bmp格式,但在技術文檔中有提到,使用jpg格式的圖片上傳會提升必定準確率,這也是咱們爬取驗證碼時使用jpg格式保存的緣由。
輸出結果中,各字段分別表明:
log_id : 惟一的log id,用於定位問題
direction : 圖像方向,傳入參數時定義爲true表示檢測,0表示正向,1表示逆時針90度,2表示逆時針180度,3表示逆時針270度,-1表示未定義。
words_result_num : 識別的結果數,即word_result的元素個數
word_result : 定義和識別元素數組
words : 識別出的字符串
還有一些非必選字段你們能夠去文檔裏熟悉一下。
接下來,咱們要作的,就是將咱們以前爬取到的驗證碼用剛介紹的OCR來識別,看看究竟能不能獲得正確結果。
和識別圖片同樣,這裏咱們將文件夾驗證碼圖片裏的圖片所有讀取出來,依次讓OCR識別,並依據「word_result_num」字段判斷是否成功識別出文本,識別出文本則打印結果,未識別出來的用「----」代替,並結合文件名對應識別結果 。最後統計識別結果數量,再來看下識別結果。
看到結果,只能說Amazing!60張圖片竟然識別出了65張,而且還有27張爲未識別出文本的,這不是我想要的結果~先來簡單看下問題出在哪裏,看到「Vertigo Captcha Image.jpg"這張圖名出現了兩次,懷疑是在識別過程當中因爲被幹擾,因此識別成兩行文字輸出了,這樣就很好解釋爲何多出來5張驗證碼圖片了。但是!爲何會有這麼多未識別出文本呢,並且英文數字組成的驗證碼識別成中文了,看樣子,不對驗證碼圖片進行去幹擾處理,僅靠OCR來識別的想法果真仍是行不通啊。那麼接下來咱們便使用圖像處理的方法來從新識別驗證碼吧。
仍是介紹驗證碼時用的這張圖
這張圖也沒能被識別出來,讓人頭禿。接下來就對這張圖片進行必定處理,看能不能讓OCR正確識別
這樣子轉化後再來看下圖片變成什麼樣了?
確實有些不一樣了,趕忙拿去試試能不能識別,仍是失敗了~~繼續修改
這裏我將圖片保存成了bmp模式,而後指定二值化的閾值,不指定的話默認爲127,咱們須要先轉化原圖爲灰度圖像,不能直接在原圖上轉化。而後將構成驗證碼的所需像素添加到一個table中,而後再使用point方法構建新的驗證碼圖片。
如今已經識別到文字了,雖然我不知道爲啥識別成了「珍」,分析以後發現是由於z我在設置參數設置了「language_type」爲「CHN_ENG」,中英文混合模式,因而我修改爲「ENG」英文類型,發現能夠識別成字符了,但依然沒有識別成功,嘗試其餘我所知道的方法後,我表示很無語,我決定繼續嘗試PIL庫的其餘方法試試。
仍是不能正確識別,我決定換個驗證碼試試。。。。。。
我找了這張帶有陰影的
簡單處理後,獲得這樣的圖片:
識別結果爲:
識別成功了,老淚縱橫!!!看樣子百度OCR仍是能夠識別出驗證碼的,不過識別率仍是有點低,須要對圖像進行必定處理,才能增長識別的準確率。不過百度OCR對規範文本的識別仍是很準確的。
那麼與其餘驗證碼相比,到底是什麼讓這個驗證碼更容易被OCR讀懂呢?
字母沒有相互疊加在一塊兒,在水平方向上也沒有彼此交叉。也就是說,能夠在每個字 母外面畫一個方框,而不會重疊在一塊兒。
圖片沒有背景色、線條或其餘對 OCR 程序產生干擾的噪點。
白色背景色與深色字母之間的對比度很高。
這樣的驗證碼相對識別起來較容易,另外,像識別圖片時的白底黑字就屬於很標準的規範文本了,因此識別的準確度較高。至於更復雜的圖形驗證碼,就須要更深的圖像處理技術或者訓練好的OCR來完成了,若是隻是簡單識別一個驗證碼的話,不如人工查看圖片輸入,更多一點的話,也能夠交給打碼平臺來識別。
做者丨HDMI
https://www.zhihu.com/people/hdmi-blog/activities
識別圖中二維碼,歡迎關注python寶典