轉(zhuǎn)載自:https://juejin.im/post/5b1b3cd26fb9a01e700ffe5b
前言
寫爬蟲有一個繞不過去的問題咆畏,那就是驗證碼制轰,比如像某乎钮糖,如果不先登陸违寞,連里面的內(nèi)容數(shù)據(jù)都爬不到辱士,而驗證碼就是網(wǎng)站進行發(fā)爬蟲的一種措施纵潦,隨著技術(shù)的發(fā)展徐鹤,驗證碼越來越復(fù)雜,爬蟲的工作越來越艱苦邀层,所以這次就來講解,怎么來識別驗證碼寥院;(聽上去口氣很大的感覺)
[圖片上傳失敗...(image-481fc8-1552112841682)]
<figcaption></figcaption>
先來看看劲赠,目前遇到的驗證碼種類有哪些?
1)圖形驗證碼
圖形驗證碼應(yīng)該是最簡單的一種驗證碼秸谢,這種驗證碼是最早出現(xiàn)凛澎,也是目前最常見的,一般組成規(guī)則是4個字母或數(shù)字或混合組成;
[圖片上傳失敗...(image-631d4b-1552112841682)]
<figcaption></figcaption>
2)滑動驗證碼
[圖片上傳失敗...(image-50e2f6-1552112841682)]
<figcaption></figcaption>
3)點觸驗證碼
[圖片上傳失敗...(image-f5e571-1552112841682)]
<figcaption></figcaption>
[圖片上傳失敗...(image-b119ee-1552112841682)]
<figcaption></figcaption>
Ok,上面這3種驗證碼方式钮追,應(yīng)該是目前PC上比較常見的驗證碼種類的预厌,當然手機app上還會有手勢驗證,宮格驗證元媚,語音驗證等等轧叽,這里就不介紹,主要針對上面常見的3種介紹刊棕;
1 圖形驗證碼
某乎的驗證碼有2種炭晒,一種是圖形驗證碼,一種是點觸驗證碼甥角,經(jīng)過測試發(fā)現(xiàn)网严,一開始是顯示圖形驗證碼,但當?shù)顷懲顺龃螖?shù)逐漸增多嗤无,就會變成點觸驗證碼震束,這種驗證碼的切換機制,也算是防爬蟲的一種手段当犯,閑話不多說垢村,先喵喵:
某乎鏈接:https://www.zhihu.com/signup?next=%2F
打開后默認是在注冊頁面,點擊下登陸按鈕嚎卫,如果還是沒有驗證碼嘉栓,刷新幾次網(wǎng)頁就行了;
[圖片上傳失敗...(image-a00e41-1552112841682)]
<figcaption></figcaption>
下面這種,下2篇文章會介紹侵佃;
[圖片上傳失敗...(image-3c41e6-1552112841682)]
<figcaption></figcaption>
2 信息介紹
識別圖形驗證碼需要安裝tesserocr這個庫麻昼,下面介紹下tesserocr;
tesserocr是Python的一個OCR識別庫馋辈,但其實是對tesseract做了一層Python Api的封裝抚芦,
核心還是tesseract,所以在安裝tesserocr之前迈螟,需要先安裝tesseract;
等下燕垃,懵逼中,tesserocr這個能看明白井联,是一個庫,但OCR是什么您旁?tesseract又是什么烙常?
OCR
OCR,全稱叫 Optical Character Recognition,中文翻譯叫光學(xué)字符識別鹤盒,是指通過掃描字符蚕脏,通過其形狀將其翻譯成電子文本的過程褥芒;
舉例:
當有一個圖形驗證碼回挽,先使用OCR技術(shù)將其轉(zhuǎn)化成電子文本,然后爬蟲將識別的結(jié)果提交到服務(wù)器衫贬,便達到自動識別驗證碼的過程尺碰;
tesseract
tesseract是google開源的OCR
OK,貌似對概念有所理解了挣棕,還有個疑問,之前有在圖形識別領(lǐng)域亲桥,還有個opencv的玩意洛心,那這兩者有什么區(qū)別?
opencv專注機器視覺
tesseract專注字符識別
所以從領(lǐng)域來說题篷,opencv更廣词身,而圖形驗證碼,opencv也可以做番枚,但殺雞焉用牛刀~
3 環(huán)境準備
windows下的安裝
在Windows下法严,要先下載tesseract,它為tesserocr提供了支持葫笼;
tesseract下載地址:https://digi.bib.uni-mannheim.de/tesseract/
打開后深啤,可以看到各種exe的列表,可以隨便挑選;
其中文件名中帶有dev的為開發(fā)版本渔欢,不帶dev則為穩(wěn)定版本墓塌,例如jb是下載 tesseract-ocr-setup-3.05.01.exe;
[圖片上傳失敗...(image-24f3a4-1552112841682)]
<figcaption></figcaption>
下載后雙擊,一路點擊苫幢,直到出現(xiàn)下面這個頁面
[圖片上傳失敗...(image-450403-1552112841682)]
<figcaption></figcaption>
這里需要勾選紅框里的Additional language data(download)访诱,這個選項是安裝OCR識別支持的語言包,這樣OCR就可以識別多國語言韩肝,然后再一路點擊NEXT即可触菜,因為要下載語言包,所以需要點時間哀峻,大概10-20分鐘左右涡相,跟網(wǎng)速有關(guān),如果不需要支持多國語言的話剩蟀,也可以不勾選催蝗,自由選擇
需要說明:默認包含英文字庫
如果,覺得一次下載那么多語言占空間育特,又或者覺得網(wǎng)速慢丙号,也可以選擇單獨安裝中文字庫;
字庫下載地址:https://github.com/tesseract-ocr/tessdata
打開后,直接搜索chi_sim.traineddata缰冤,這個代表的就是中文犬缨,下載下來;
然后找到剛剛tesseract安裝目錄,里面會有一個叫tessdata的目錄棉浸,直接把剛下載的語言包放到這個目錄下即可怀薛;
[圖片上傳失敗...(image-2f0ccc-1552112841682)]
<figcaption></figcaption>
如何驗證tesseract是否安裝成功?直接cmd下輸入tesseract即可迷郑;
成功會直接顯示信息;
[圖片上傳失敗...(image-e4152d-1552112841682)]
<figcaption></figcaption>
如果提示'tesseract' 不是內(nèi)部或外部命令枝恋,則是因為沒有配置環(huán)境變量,手動把tesseract根目錄配置到path參數(shù)下即可三热,這塊不詳細說明鼓择;
到此為止,tesseract安裝成功啦~
接下來就安裝tesserocr就漾,直接pip命令即可:
pip3 install tesserocr install
復(fù)制代碼
但jb在安裝的時候呐能,直接報錯:
[圖片上傳失敗...(image-9bb5ad-1552112841682)]
<figcaption></figcaption>
試過很多種方式,就算使用conda install tesserocr,也一樣報錯抑堡。
[圖片上傳失敗...(image-b2ed56-1552112841682)]
<figcaption></figcaption>
經(jīng)歷千辛萬苦摆出,終于找到一條可行的命令:
conda install -c simonflueckiger tesserocr
復(fù)制代碼
[圖片上傳失敗...(image-b0883e-1552112841682)]
<figcaption></figcaption>
最終就安裝上tesserocr啦~
如何驗證是否真的安裝了?很簡單首妖,直接import tesserocr偎漫,不報錯就說明安裝好了;
[圖片上傳失敗...(image-6101ac-1552112841682)]
<figcaption></figcaption>
對了有缆,如果有同學(xué)不知道conda這條命令的話象踊,請訪問下面的鏈接温亲,直接搜索scrapy安裝,會有介紹conda:
https://juejin.im/post/5afcb91251882565bd257097|
OK杯矩,windows下的tesserocr跟tesseract的環(huán)境已經(jīng)安裝好了栈虚;
別著急,順便介紹下Linux跟Mac史隆,但以下方式均未經(jīng)過jb驗證魂务,信息來源于網(wǎng)上,僅供參考:
Linux下的安裝
對于Liunx來說泌射,不同系統(tǒng)已經(jīng)有了不同的發(fā)行包了粘姜,它可能叫做tesseract-ocr或者tesseract,直接用對應(yīng)的命令安裝即可;
-
Ubuntu熔酷、Debian和Deepin
在Ubuntu孤紧、Debian和Deepin系統(tǒng)下,安裝命令如下:sudo apt-get install-y tesseract-ocr libtesseract-dev libleptioica-dev 復(fù)制代碼
-
CentOS拒秘、Red Hat 在CentOS和Red Hat系統(tǒng)下坛芽,安裝命令如下:
yum install -y tesseract 復(fù)制代碼
在不同發(fā)行版本運行如上命令,即可完成tesseract的安裝翼抠;
安裝完成后,便可以調(diào)用tesseract命令获讳;
默認也是指安裝英文語言阴颖,如果需要安裝其他語言,請看下上面Windows的介紹丐膝,一樣的處理方案量愧,這里不重復(fù)說明;
接下來就是安裝tesserocr,直接使用pip安裝:
pip3 install tesserocr pillow
復(fù)制代碼
Mac下的安裝
在Mac下帅矗,首先使用Homebrew 安裝ImageMagick 和tesseract庫:
brew install imagemagick
brew install tesseract --all-languages
復(fù)制代碼
接下來再安裝tesserocr即可:
brew install tesserocr pillow
復(fù)制代碼
4 識別測試
為了方便測試偎肃,需要把驗證碼的圖片保存到本地;
打開weibo.com浑此,隨便輸入賬號密碼累颂,會提示輸入驗證碼,打開開發(fā)者工具凛俱,找到驗證碼元素紊馏,它的src屬性就是一個鏈接,copy出來直接打開蒲犬,會看到一個驗證碼朱监,而且刷新的驗證碼會變化,由此推斷這是個驗證碼的接口原叮,右鍵保存驗證碼即可赫编,就得到一張驗證碼巡蘸;
驗證碼鏈接:
https://login.sina.com.cn/cgi/pin.php?r=9967937&s=0&p=gz-d0dc363f6a4523cbd602a5a10f00c59b4784
[圖片上傳失敗...(image-f3a7fe-1552112841681)]
<figcaption></figcaption>
[圖片上傳失敗...(image-afd087-1552112841681)]
<figcaption></figcaption>
ok,完事具備,那就開始吧擂送,新建項目悦荒,把驗證碼放到項目根目錄下;
用tesserocr庫來識別驗證碼:
import tesserocr
from PIL import Image
#新建Image對象
image = Image.open("3.jpg")
#調(diào)用tesserocr的image_to_text()方法团甲,傳入image對象完成識別
result = tesserocr.image_to_text(image)
print(result)
復(fù)制代碼
[圖片上傳失敗...(image-467ae7-1552112841681)]
<figcaption></figcaption>
結(jié)果逾冬,運行后,啥都沒有躺苦?身腻??
接下來jb陷入了困擾匹厘,包括調(diào)試嘀趟,找各種文檔,最終愈诚,把上面調(diào)試的驗證碼換了一個:
[圖片上傳失敗...(image-4c4e95-1552112841681)]
<figcaption></figcaption>
替換下圖片她按,再執(zhí)行一次代碼:
[圖片上傳失敗...(image-9bb8b6-1552112841681)]
<figcaption></figcaption>
OK,看到是有數(shù)據(jù)了炕柔,不過輸出的是MEEE酌泰,跟驗證碼的ME8E還是有點不一樣;
目前兩個問題:
1)微博的驗證碼識別失敗匕累,輸出空
2)第二章驗證碼部分詞識別有誤
心想陵刹,這庫是網(wǎng)上都推薦用的,是Google開源的欢嘿,理論上沒問題衰琐,而且人家也都這么用,為什么這里就有問題炼蹦?難道還需要額外的處理羡宙?
懷著疑問跟夢想,繼續(xù)學(xué)習(xí)掐隐;
題外話: tesserocr還有一個更加簡單的方法狗热,這個方法可直接將圖片文件轉(zhuǎn)換成字符串,代碼如下:
import tesserocr
print(tesserocr.file_to_text("1.jpg"))
復(fù)制代碼
[圖片上傳失敗...(image-47278c-1552112841681)]
<figcaption></figcaption>
結(jié)果也跟上面的一樣虑省,但網(wǎng)上不建議這么用斗搞,原因是據(jù)說這種識別效果不如上一種的好;
關(guān)于微博驗證碼為空慷妙,使用tesseract輸出下原因:
tesseract 圖片路徑 output
復(fù)制代碼
[圖片上傳失敗...(image-e8ce79-1552112841681)]
<figcaption></figcaption>
leptonica 在解析時沒有檢測到任何dpi僻焚;
5 驗證碼處理
網(wǎng)上找了下信息,比如這張驗證碼:
[圖片上傳失敗...(image-8e7a15-1552112841681)]
<figcaption></figcaption>
可能是驗證碼內(nèi)的多余線條干擾了圖片的識別膝擂;
又比如微博這張:
[圖片上傳失敗...(image-858d87-1552112841681)]
<figcaption></figcaption>
可能是字體位置虑啤,跟圖案等因素干擾了圖標的識別隙弛;
解決方案還是有的,需要對圖片進行額外的處理狞山,如轉(zhuǎn)灰度全闷,二值化等操作;
轉(zhuǎn)灰度處理: 利用Image對象的convert()方法參數(shù)傳入L萍启,即可將圖片轉(zhuǎn)成為灰度圖像:
from PIL import Image
image = Image.open("1.jpg")
image = image.convert('L')
image.show()
復(fù)制代碼
[圖片上傳失敗...(image-f22f8e-1552112841681)]
<figcaption></figcaption>
圖片成功轉(zhuǎn)灰了总珠;此時我們再校驗一下,發(fā)現(xiàn)校驗還是MEEE勘纯,失斁址;[圖片上傳失敗...(image-c3c54a-1552112841681)]
<figcaption></figcaption>
傳入1的后驳遵,即可將圖片進行二值化處理:
(二值化是指將圖像上的像素點的灰度值設(shè)置為0或255淫奔,也就是將整個圖片呈現(xiàn)出明顯的只有黑和百的視覺效果)
import tesserocr
from PIL import Image
image = Image.open("1.jpg")
image = image.convert('1')
image.show()
復(fù)制代碼
[圖片上傳失敗...(image-6a2b17-1552112841681)]
<figcaption></figcaption>
這個一看,比上面更模糊了堤结,理所當然的唆迁,校驗結(jié)果會錯的更加離譜:[圖片上傳失敗...(image-b4154e-1552112841681)]
<figcaption></figcaption>
二值化的閾值是可以指定的,上面的方法采用的是默認閾值127竞穷;但一般很少直接轉(zhuǎn)換原圖唐责,原因如上可看到,錯誤的更加離譜了瘾带;
一般是先將原圖轉(zhuǎn)為灰度圖像妒蔚,然后再指定二值化的閾值,代碼如下:
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)
#通過表格轉(zhuǎn)換成二進制圖片月弛,1的作用是白色,不然就全部黑色了
image = image.point(table,"1")
image.show()
result = tesserocr.image_to_text(image)
print(result)
復(fù)制代碼
這里說明下科盛,可能有同學(xué)對256不明白帽衙,這是什么?
首先贞绵,我們是把圖片置灰處理厉萝,灰度圖像是一種具有從黑到白256級灰度色階或等級的單色圖像;
對于灰度圖像利用閾值得到二值化的圖像榨崩, 也就是說谴垫,我們設(shè)定了一個閾值,從0到256母蛛,如果灰度圖像少于閾值則設(shè)置0翩剪,大于閾值則設(shè)置1,0是黑色彩郊,1是白色前弯,這樣做蚪缀,就可以把一個灰度圖完全轉(zhuǎn)換二值化圖;
可能還是懵逼恕出,直接貼圖:
原圖
[圖片上傳失敗...(image-136781-1552112841680)]
<figcaption></figcaption>
灰度圖:
[圖片上傳失敗...(image-d250a7-1552112841680)]
<figcaption></figcaption>
二值圖:
[圖片上傳失敗...(image-9065a-1552112841680)]
<figcaption></figcaption>
在灰度圖上询枚,部分色彩是介于白色跟黑色之間,所以通過設(shè)置閾值的方法浙巫,把這些中間色彩全部轉(zhuǎn)換成黑色跟白色金蜀;
ok,扯遠了,上面把驗證碼二值圖后是長這樣的:
[圖片上傳失敗...(image-61abbe-1552112841680)]
<figcaption></figcaption>
而校驗結(jié)果:
[圖片上傳失敗...(image-4b528-1552112841680)]
<figcaption></figcaption>
good的畴,有所變化渊抄, 至少不是MEEE了,那我們繼續(xù)調(diào)苗傅,調(diào)到一個合適的值;
調(diào)了半天抒线,jb放棄了,原因是這個8渣慕,不管怎么調(diào)都調(diào)不到一個合適的值嘶炭,一直在S、R逊桦、B之間徘徊眨猎;
JB換了個驗證碼:
[圖片上傳失敗...(image-458247-1552112841680)]
<figcaption></figcaption>
上面同樣的代碼,無修改强经,二值圖如下:
[圖片上傳失敗...(image-7e83e0-1552112841680)]
<figcaption></figcaption>
校驗結(jié)果:
[圖片上傳失敗...(image-94537a-1552112841680)]
<figcaption></figcaption>
oh year睡陪,這個能校驗出來了~
還記得我們一開始那個微博驗證碼嗎?我們也來試試匿情,處理后的驗證碼是這樣的~
[圖片上傳失敗...(image-be6724-1552112841680)]
<figcaption></figcaption>
結(jié)果校驗的時候兰迫,基本上都空,只有在138的時候會有一點點識別效果炬称,但是壓根不搭邊汁果;[圖片上傳失敗...(image-74a09c-1552112841680)]
<figcaption></figcaption>
對比了下,微博驗證碼跟上面能識別的驗證碼:
[圖片上傳失敗...(image-f677e4-1552112841680)]
<figcaption></figcaption>
[圖片上傳失敗...(image-27e8d9-1552112841680)]
<figcaption></figcaption>
能別識別的玲躯,是實心据德,而不能被識別的,是空心跷车;
實心的好處在于棘利,圖像處理后,黑白分明朽缴,但是空心在圖像處理后善玫,由于線條本來就很細,處理后可能都識別不出來了密强;
6 中文情況如何蝌焚?
更新于18.6.11
突然想起裹唆,上面安裝的時候有提及到安裝不同語言包,那如果要看看其他語言只洒,怎么搞许帐?因此就補充這點了~
先上圖~
[圖片上傳失敗...(image-6609fb-1552112841680)]
<figcaption></figcaption>
直接上代碼:
import tesserocr
from PIL import Image
image = Image.open("juejin.jpg")
result = tesserocr.image_to_text(image, lang='chi_sim')
print(result)
復(fù)制代碼
因為默認是英文,所以英文不需要指定lang毕谴,但中文就需要啦成畦,chi_sim就是簡體中文了;
[圖片上傳失敗...(image-f74b26-1552112841680)]
<figcaption></figcaption>
從輸出的結(jié)果來看涝开,小冊那估計有個sale循帐,不然估計開源庫也能匹配出來~
但依然可以看出,中文也不是很精準~
這里說明下舀武,中午不需要置灰跟二值哈拄养,不然顏色加深了,估計更難辨別了~
7 小結(jié)
本章學(xué)習(xí)了tesserocr及tesseract的環(huán)境搭建银舱,以及如何對圖形驗證碼進行噪音處理瘪匿,并且講解灰色圖跟二值圖的概念;
作者:jb
鏈接:https://juejin.im/post/5b1b3cd26fb9a01e700ffe5b
來源:掘金
著作權(quán)歸作者所有寻馏。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)棋弥,非商業(yè)轉(zhuǎn)載請注明出處。