使用Python和Tesseract來識別圖形驗證碼

2020-12-03 FreeBuf

*本文原創作者:ipenox,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載

各位在企業中做Web漏洞掃描或者滲透測試的朋友,可能會經常遇到需要對圖形驗證碼進行程序識別的需求。很多時候驗證碼明明很簡單(對於非網際網路企業,或者企業內網中的應用來說特別如此),但因為沒有趁手的識別庫,也只能苦哈哈地進行人肉識別,或者無奈地放棄任務。在這裡,我分享一下自己使用Python和開源的tesseract OCR引擎做驗證碼識別的經驗,並提供相關的原始碼和示例供大家借鑑。

一、關於圖形驗證碼識別與tesseractOCR

儘管多數圖型驗證碼只有區區幾個數字或字母,但你可能聽說了,在進行機器識別的過程中,你要收集樣本,對圖片去噪、二值化、提取字符、計算特徵,甚至還要祭出神經網絡去訓練數據進行機器學習……還沒開幹,退堂鼓早打響三遍了。其實我根本不想去鑽研那麼多高深的理論,只想要寥寥數行Python代碼就搞定它,然後把主要精力投入到更重要的滲透測試中去。在這種情況下,tesseract就能幫上大忙了。

Tesseract的OCR引擎最早是HP實驗室開發的,曾經是 OCR業內最準確的三款識別引擎之一。2005年該引擎交給了Google,作為開源項目發布在Google Project上了。Tesseract提供獨立程序和API兩種形式供用戶使用。純白色背景、字符規整無幹擾像素的驗證碼圖片可以直接調用tesseract程序來進行識別。如要更方便靈活地在自己的程序中進行識別,則可以使用tesseract的API。

二、Tesseract的編譯和安裝

Tesseract的項目主頁(https://github.com/tesseract-ocr/tesseract)上wiki中有詳細的編譯安裝步驟,大家可以參考,本文中我們將以3.05.01版本為基礎。我的系統環境是RHEL 7.4,64位版本。首先用yum安裝各種依賴的圖形庫,然後用源碼安裝Leptonica(官方主頁http://www.leptonica.com/download.html,版本需要1.74以上),編譯安裝很簡單,解壓後,以默認參數依次執行configure,make,make install命令即可。安裝完之後需執行:

exportPKG_CONFIG_PATH=/usr/local/lib/pkgconfig不然在下一步tesseract的configure腳本會報找不到Leptonica。

將tesseract的源碼解壓後進入到源碼主目錄下依次執行:

./autogen.sh./configure--with-extra-libraries=/usr/local/libmakemake install即可成功安裝。

根據項目wiki,Data Files節的指南下載相應的數據文件,因為我們只識別英文和數字驗證碼,所以下載3.04/3.05版本的英語文件eng.traineddata即可,下載後放到/usr/local/share/tessdata目錄下。至此,tesseract就安裝完畢了。

三、為Python封裝tesseract API

tesseract提供的是C++ API(接口界面是TessBaseAPI類),最核心的函數就是TessBaseAPI::TesseractRect這個函數。為了能在Python中方便地使用,我將其封裝為Python模塊了,詳細代碼放在github上:https://github.com/penoxcn/Decaptcha。該模塊名為decaptcha,源文件包括以下四個文件:

setup.py、decaptcha.i、decaptcha.h和depcaptcha.cpp。

將以上文件放在同一個臨時目錄下,然後執行以下命令進行編譯和安裝:

python setup.py install安裝時需要調用swig命令,所以系統需要先安裝swig。

如果tesseract不是安裝在默認的路徑下,請參照setup.py代碼自行修改相關的頭文件和庫文件的路徑即可。

安裝完之後進入Python交互環境試著import一下看是否正常:

from decaptcha import Decaptcha如果報錯找不到libtesseract,那可能是tesseract的庫目錄(/usr/local/lib)沒有在Python的庫搜索目錄中。這時候可以將tesseract的庫目錄添加到系統的/etc/ld.so.conf文件中(加了之後需要執行ldconfig命令以生效);或者每次import decaptcha模塊之前,都先執行以下Python代碼:

import syssys.path.append("/usr/local/lib")四、安裝Python PIL庫

PIL的全稱是Python Imaging Library,是一個強大而易用的圖像庫。在其主頁(http://pythonware.com/products/pil/)下載最新版(截止目前是1.1.7)原始碼進行安裝。安裝之前確保系統已安裝了png/jpeg/tiff等圖像庫。解壓縮之後,在主目錄下執行python setup.py install即可。

使用很簡單,下面的代碼片段從任意格式圖片文件創建一個Image對象,進行格式轉換,獲得其大小和像素數組,只需幾行代碼:

from PIL import Imageimg = Image.open('test.png') # Your image here! img = img.convert("RGBA") pixdata = img.load() width,height = img.sizeprint 'imgsize: %dx %d' % (width, height)print'pixel[2,4]:', pixdata[2, 4] #eg,(0xD3,0xD3,0xD3,0xFF)五、實戰驗證碼識別

至此,進行圖形驗證碼識別的依賴環境都已準備好,我們可以開幹了。

識別的流程簡單來說如下:

1. 用Image加載圖像,轉為RGBA格式,然後獲取像素數據;2. 將RGBA格式的像素數據轉換為0和1的字節串(其實就是二值化處理);3. 調用decaptcha模塊進行圖像識別,獲得驗證碼字符串

實際的代碼也非常簡單,請看我項目Decaptcha目錄下的decaptcha_test.py文件,關鍵代碼也就十幾行。影響代碼長短或複雜性的,就是二值化這一步了。其實很多圖形驗證碼比較簡單,細心分析一下,不難得出二值化的條件。下面以我工作中遇到過的一些驗證碼為例:

有5組,均來自於我公司的不同業務網站。識別代碼請參看我項目目錄下decaptcha_demo.py文件,所有的示例驗證碼放在images目錄下。大家可以用圖片編輯器打開相關的驗證碼文件觀察和分析像素的規律。

第一組aa系列,字符顏色偏白,背景偏黑,所以可試著以像素RGB均值(或總和)大於某個數值為條件進行轉換:r+g+b>=480則為1,否則為0。

第二組bb系列,字符有顏色,背景偏白色,轉換條件考慮為RGB中是否有兩個要素大於0xf0:int(r/240)+int(g/240)+int(b/240) <=1則為1,否則為0。

第三組cc系列,字符和背景都是單色,但是有不固定位置的點幹擾,幹擾點顏色與字符顏色相同,但是都是離散的。這種情況下,像素是白色的就是背景0,否則再判斷一下是否離散的點,可以簡單地判斷它右邊和下邊的點是否都是白色背景來判定。

第四組dd系列,字符顏色偏紫色,並且有背景幹擾線。通過將一些樣本圖片的每個像素的RGB值列印出來,確赫然發現字符像素的G通道值都為0,其它情況要麼是背景,要麼是幹擾線。

第五組ee系列是最複雜的,有幹擾線,幹擾點,字符也有變形,顏色也不固定。實際上它來源於一個叫做securimage的php庫所產生,恐怕不能一兩行代碼就二值化了。但是仔細觀察它的模式會發現,它的大背景、幹擾線、幹擾點、字符都是用同一種顏色產生。所以我們可以以統計數量的方式來找出哪些是背景顏色(出現次數最多的自然是背景顏色)。另外我們再統計每個字符的顏色與背景顏色的偏差(將rgb差值的平方加起來),找出幹擾線、字符與背景色的偏差值的閾值範圍,再將其在二值化的時候進行應用,也可以成功地將其二值化。而字符變形的問題則不需要擔心,交給tesseract就可以了。

在二值化的時候,我在屏幕上用# 符號列印出了二值化後的圖像,大家可以看下效果:

python decaptcha_demo.py aa aa1.gif

驗證碼實際是5648,識別為5649,錯了一位。

下面來個正確識別的:

python decaptcha_demo.py bb bb1.jpg

第五組的識別情況:

python decaptcha_demo.py ee ee9.png > 1.txt因圖片有點長,超過了終端的列數,故輸出到txt文件後再用notepad++打開的:

驗證碼實際是912065,識別為912085,錯了一位。

再看看總體成績如何:

aa組10個驗證碼,整體正確識別的有5個。bb組10個驗證碼,整體正確識別的3個。cc組10個驗證碼,整體正確識別的9個。dd組10個驗證碼,整體正確識別的3個。ee組10個驗證碼,整體正確識別的4個。

aa組、cc組和ee組識別得還可以,沒有識別出來的多數僅錯了一個字符。而bb和dd組識別得較差,沒有識別出來的可能都錯了兩三個字符。

這份成績單,咋看之下,有些朋友可能覺得很不好看。但是,請不要太悲觀,要想想投入產出比,大多數情況下,除了固定的模式化代碼外,我們只需要編寫寥寥幾行二值化的代碼就可以收穫輸出了啊,這意味著在測試時,程序自動化就可以搞了啊:不求百分之一百,只求十裡有一發。即使只有30%的識別率,連續識別5個圖片,獲得其中一個準確識別的概率也達到了86%,無非多浪費一些Web請求而已。

因為Image庫支持從內存中加載圖片,所以與requests庫的結合也是非常的方便,直接通過HTTP請求下載下來,將內容丟給Image就可以了:

import requests,StringIOr =requests.get(imgurl)imgbuf = StringIO.StringIO(r.content)img =Image.open(imgbuf)是不是很簡單很愉快?

六、後記

通過以上的例子和代碼,大家可以初探tesseract的能力。實際上tesseract支持學習,通過樣本訓練,可以大幅提高它的識別準確率,當然這個過程就有點複雜了,也不符合本文追求敏捷的宗旨。經過多年的技術對抗,傳統的圖片驗證碼已經顯得過時了,但仍有很多企業網站在大量使用,希望本文能夠給大家一些啟發和幫助。

*本文原創作者:ipenox,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載

相關焦點

  • Python驗證碼識別:利用pytesser識別簡單圖形驗證碼
    圖形通常由點、線、面、體等幾何元素和灰度、色彩、線型、線寬等非幾何屬性組成。計算機涉及到的幾何圖形處理一般有 2維到n維圖形處理,邊界區分,面積計算,體積計算,扭曲變形校正。對於顏色則有色彩空間的計算與轉換,圖形上色,陰影,色差處理等等。在破解驗證碼中需要用到的知識一般是 像素,線,面等基本2維圖形元素的處理和色差分析。
  • 用python識別驗證碼
    前言經常大家在做自動化測試或者做網絡爬蟲的時候,都很容易遇到驗證碼。今天,我們就簡單的說下,怎麼用python來處理驗證碼。
  • Python3爬蟲-10:Tesseract 圖像識別
    ,如:圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、微博宮格驗證碼等;這時,可以利用OCR技術識別圖形驗證碼進行驗證。OCR,即Optical Character Recognition,是指光學字符識別,通過掃描字符將其形狀翻譯成電子文本。在Python3中,可以通過pytesseract庫調用Tesseract-OCR使用OCR技術識別圖形驗證碼。
  • mac使用python識別圖形驗證碼!
    前言首先這篇文章,主要是研究圖形驗證碼,後期會不定時拓展內容。
  • Python3網絡爬蟲課程 8.1圖形驗證碼的識別
    目前,很多網站都採取了各種各樣的反爬措施,其中之一便是使用驗證碼.隨著技術的發展,驗證碼卻來越複雜,花樣越來越多,爬蟲的工作也變得愈加複雜,本節將介紹圖形驗證碼的識別.圖形驗證碼我們首先將識別最簡單的驗證碼,圖形驗證碼.目標我們將以知網為例講解使用 OCR 技術識別圖形驗證碼.
  • python人工智慧-圖像識別
    pytesseract:圖像識別庫。我這裡使用的是python3.6,PIL不支持python3所以使用如下命令pip install pytesseractpip install pillow如果是python2,則在命令行執行如下命令:pip install pytesseractpip install PIL這時候我們去運行上面的代碼會發現如下錯誤
  • 用Python識別圖形驗證碼,實現自動登陸!
    驗證碼有圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、宮格驗證碼。這回重點講講圖形驗證碼的識別。雖說圖形驗證碼最簡單,但是對於我這等新手,還是要苦學一番。首先尋找測試網站,網站選的是如雲閣小說網,小網站不怕被封。他
  • 驗證碼識別實例,python簡單圖像處理和實現
    圖像分析所以我最終下載了一個這樣的圖像,並使用一個工具(binary-image)以二進位形式可視化圖像(0表示黑色,1表示白色像素)。我的觀察沒錯,圖像尺寸為45x180,每個字符分配30個像素的空間來適配,從而使它們間隔比較均勻。因此,取得了驗證碼識別路上的第一步,結果:把圖像裁剪成6個不同的部分,每個部分的寬度為30像素。
  • 12306將剔除辨識率低圖形驗證碼
    同時,近日360瀏覽器也宣布,已全面攻破了12306圖形驗證碼,實現了全自動識別技術,並首次公布了581種12306圖形驗證碼大數據。  對此,杭州微觸科技有限公司負責人宋超表示,圖片的數量不是一個固定的數字,是不斷動態增替的過程,會「自己不斷通過用戶的使用數據來更新。」
  • 圖形驗證碼難防黃牛 今年網購車票超8成無驗證碼
    中國鐵路總公司表示,今年春運網絡購票需要驗證碼的比例將被壓縮到15%以下。昨天,老牌搶票軟體360瀏覽器表示通過大數據分析,今年春運搶票初期,12306的圖形驗證碼並沒有比去年增加難度,他們發現圖形驗證碼已經不是鐵路防止黃牛倒票的主要技術手段,鐵路正在通過更加嚴格的實名認證等其他方式來防黃牛,提高了用戶的購票體驗。
  • 12306圖形驗證碼讓人"吐槽" 驗證碼到底有什麼用
    在年底的網絡購票高峰中,中國鐵路客戶服務中心的12306圖形驗證碼系統被很多購票者「吐槽」。人們不禁要問,複雜的驗證碼系統,到底有什麼用?其實,驗證碼存在的最大意義,就是區分在頁面上進行輸入操作的是人還是自動化的軟體。
  • 能跑源碼,還提供數據集:這裡有一個入門企業級驗證碼識別項目
    前言網上關於驗證麼識別的開源項目眾多,但大多是學術型文章或者僅僅是一個測試 demo,那麼企業級的驗證碼識別究竟是怎樣的呢?前方高能預警,這是一個生產水準的驗證碼識別項目,筆者可以向你們保證,它一定會是各位所見過的文章中最實用的,你甚至可以不需要懂代碼寫代碼就能輕鬆使用它訓練一個 99 識別率的模型。這才是企業級應該有的樣子:算法開發負責框架,訓練只需要一個實習生。
  • 要選對12306購票圖形驗證碼 比高考還難
    本組圖表由受訪者供圖商報記者 黎靜 饒方婧「橙子和橘子,章魚和魷魚,傳真機和電話……」這些物品你分得清楚嗎?近日就有不少網友吐槽,這些五花八門的火車票圖形驗證碼讓人大傷腦筋:圖片小且像素低,讓人很難看清楚。
  • 12306網站驗證碼遭拍磚 「驗證碼」本意是安全不是麻煩
    圖像驗證碼又可以細分為靜止圖像或視頻驗證碼。前者主要是需要用戶對一幅靜止圖像中的物體進行辨識,而後者需要用戶對視頻中動態出現的物體進行區分與辨別。動態視頻驗證碼技術上具有先進性,但網站投入成本較高,目前還未普及。  為什麼一定要用圖形驗證碼?  「黃牛不可能人工去買票,必然是使用搶票軟體。」
  • 使用一行Python代碼從圖像讀取文本
    但在這裡,情況正好相反——對你來說很瑣碎的任務,比如識別圖像中的貓或狗,對電腦來說真的很難。在某種程度上,我們是天造地設的一對。至少現在是這樣。雖然圖像分類和涉及到一定程度計算機視覺的任務可能需要大量的代碼和紮實的理解,但是從格式良好的圖像中讀取文本在Python中卻是簡單的,並且可以應用於許多現實生活中的問題。
  • Python圖像處理之圖片文字識別(OCR)
    可以實現OCR 的底層庫並不多,目前很多庫都是使用共同的幾個底層OCR 庫,或者是在上面進行定製。  Tesseract 是一個OCR 庫,目前由Google 贊助(Google 也是一家以OCR 和機器學習技術聞名於世的公司)。Tesseract 是目前公認最優秀、最精確的開源OCR 系統。  除了極高的精確度,Tesseract 也具有很高的靈活性。
  • 網購火車票超八成無需驗證碼 只隨機出現
    中國鐵路總公司表示,今年春運網絡購票需要驗證碼的比例將被壓縮到15%以下。昨天,老牌搶票軟體360瀏覽器表示通過大數據分析,今年春運搶票初期,12306的圖形驗證碼並沒有比去年增加難度,他們發現圖形驗證碼已經不是鐵路防止黃牛倒票的主要技術手段,鐵路正在通過更加嚴格的實名認證等其他方式來防黃牛,提高了用戶的購票體驗。
  • 最全的 Python 反爬蟲及應對方案!
    圖片被識別為「鍋鏟」之後,那麼下次這張圖片再出現的時候,系統就直接判斷它是「鍋鏟」。時間一長,圖片驗證碼伺服器裡的圖片就被標記完了,機器就能自動識別了。簡單型上面兩個不用處理直接可以用OCR識別技術(利用python第三方庫--esserocr)來識別。經過灰度變換和二值化後,由模糊的驗證碼背景變成清晰可見的驗證碼。
  • 使用python3+opencv3實現的識別答題卡的例子(01)
    由於工作需要,最近在研究關於如何通過程序識別答題卡的客觀題的答案,之前雖然接觸過python,但對於計算機視覺這一塊卻完全是一個陌生的領域,經過各種調研
  • Python3網絡爬蟲課程 8.2極驗滑動驗證碼的識別
    上一節了解了簡單驗證碼的識別,但是現在這種驗證碼非常少見,現在出現了一大批新型的驗證碼,如極驗滑動驗證碼,它需要拖動合併滑塊才能完成識別。目標本節目標是識別極驗滑動驗證碼,如分析思路、識別缺口、生成拖動路徑、模擬合併等。