工具應用:利用Tesseract-OCR實現驗證碼識別

實驗簡介

光學字元識別(OCR,Optical Character Recognition)是指對文本資料進行掃描,然後對圖像文件進行分析處理,獲取文字及版面信息的過程。OCR技術非常專業,一般多是印刷、列印行業的從業人員使用,可以快速的將紙質資料轉換為電子資料。

Tesseract的OCR引擎最先由HP實驗室於1985年開始研發,至1995年時已經成為OCR業內最準確的三款識別引擎之一。Tesseract目前已作為開源項目發布在Google Project,其最新版本3.0已經支持中文OCR,並提供了一個命令行工具。

驗證碼是一種區分用戶是計算機還是人的公共全自動程序。可以防止:惡意破解密碼、刷票、論壇灌水,有效防止某個黑客對某一個特定註冊用戶用特定程序暴力破解方式進行不斷的登陸嘗試,實際上用驗證碼是現在很多網站通行的方式。由於驗證碼可以由計算機生成並評判,但是必須只有人類才能解答,所以回答出問題的用戶就可以被認為是人類。

但是在我們的測試開發過程中,難免會存在需要使用到驗證碼的時候,所以本實驗則主要利用Java通過封裝Tesseract-OCR命令和調用Tess4J兩種方式,實現驗證碼的識別。

實驗目的

(1)理解驗證碼的工作原理和應用場景。

(2)熟練使用Tesseract-OCR的命令完成對一張圖片驗證碼的識別。

(3)使用Java調用Tesseract-OCR的命令完全圖片的驗證碼自動化處理。

(4)使用Tess4J完成驗證碼的識別處理。

(5)利用Java通過封裝完成對一個站點的驗證碼自動化識別處理。

實驗流程

  1. 關於驗證碼

驗證碼是防止程序對一個站點發起自動化請求的很重要的一種手段,特別是實現登錄的過程,向站點提交數據的過程等,我們必須有一種機制防止自動化程序向網站發起請求。

所謂道高一尺,魔高一丈。驗證碼和破解驗證碼就在雙方的拉鋸戰中越來越厲害,越來越難以破解。目前的驗證碼通常的種類及特點如下:

(1)最基礎的英文驗證碼:純粹的英文與數字組合,白色背景,這是最容易實現OCR識別的驗證碼。

(2)字體變形的英文驗證碼:可以通過簡單的機器學習實現對英文與數字的識別,準確率較高。

(3)加上擾亂背景線條的驗證碼:可以通過程序去除干擾線,準確率較高。

(4)中文驗證碼:中文由於字體多樣,形狀多變,數量組合眾多,實現起來難度較大,準確率不高。

(5)中文字體變形驗證碼:準確率更低。

(6)中英文混合驗證碼:非常考驗OCR程序的判斷能力,基本上識別起來非常有難度。

(7)提問式驗證碼:這是需要OCR結合人工智慧才能實現,目前基本上無法識別。

(8)GIF動態圖驗證碼:由於GIF圖片是動態圖,無法定位哪一幀是驗證碼,所以難度很大。

(9)划動式驗證碼:雖然程序可以模擬人的操作,但是具體拖動到哪個位置很難處理。

(10)視頻驗證碼:目前OCR識別還未實現。

(11)手機驗證碼:手機驗證碼實現自動化是很容易的,但是手機號碼不那麼容易獲得。

(12)印象驗證碼:目前無解。

我們可以看到上述形形色色的驗證碼,目前用純粹的技術手段是很難處理驗證碼問題的。所以,也有很多人看到這件事情的價值,專門僱傭大量人員幫助客戶實現人工打碼,把它變成了一門生意。

2. Tesseract-OCR基礎使用

(1)下載Tesseract-OCR,官方網站為:sourceforge.net/project

(2)安裝Tesseract-OCR,建議安裝在不包含空格的路徑里,不要安裝在默認的Program Files文件夾。比如筆者的安裝路徑為:C:ToolsTesseract-OCR 。

(3)在環境變數中添加TESSDATA_PREFIX變數,值為OCR安裝目錄:C:ToolsTesseract-OCR。

(4)準備一些英文和數字的驗證碼,可以帶背景干擾線。比如將此驗證碼圖片保存在D:OtherVerifyCode目錄中。

(5)打開CMD命令行程序,執行如下命令,即可將識別到的驗證碼內容輸出到一個.txt文本文件中。

C:/Tools/Tesseract-OCR/tesseract.exe D:/Other/VerifyCode/myverifycode.jpg D:/Other/VerifyResult/output

我們來看看具體的運行效果:

我們可以看到,tesseract.exe是執行識別的主命令,後面跟的第一個參數為指定驗證碼圖片所在的路徑和文件名,第二個參數為識別結果的輸出路徑,此處指輸出到文件D:/Other/VerifyResult/output.txt中,但是我們不需要在後面特別添加.txt後綴。

(6)如果我們想實現中文的驗證,則需要下載中文訓練字型檔文件,文件名為:chi_sim.traineddata,將該文件下載到電腦後,保存至C:ToolsTesseract-OCR essdata文件夾中。

(7)識別中文驗證碼時只需要在正常命令後面添加「 –l chi_sim」指定訓練字型檔文件即可。

C:/Tools/Tesseract-OCR/tesseract.exe 驗證碼所在路徑 結果輸出路徑 -l chi_sim

事實上,Tesseract-OCR默認使用的是英文字型檔,字型檔名稱為eng.traineddata,我們也可以下載更多的字型檔來對其識別的準確率進行擴展。

3. 使用Java調用Tesseract-OCR命令完成識別

由於Tesseract-OCR並沒有專門提供編程介面,所以我們不能直接通過引入Jar包的方式來進行調用。但是由於Tesseract-OCR是通過命令來完成識別的,所以我們就可以讓Java去執行這段命令。並且識別到的結果也是輸出到文件中,所以我們自然可以利用Java去讀取這段文本內容,進而獲得識別到的結果。下面我們來看看具體的實現過程。

(1)Java執行Windows命令主要通過Runtime對象來完成。所以我們自然會需要調用該對象執行命令。

(2)由於命令當中有三個核心參數,驗證碼路徑,輸出路徑,字型檔名稱,所以我們需要使用編程的方式對該參數進行拼接,最後變成一個字元串完成命令的發送和執行。

(3)我們的驗證碼圖片的路徑和名稱不一樣,所以我們的識別程序應該將其參數化。同時,也可根據自身需要對三個核心參數均使用形式參數的方式在調用該識別程序時傳遞進來。

(4)我們需要判斷命令是否執行成功,如果沒有執行成功,則提示出錯信息,否則,讀取該輸出文件的內容,並將其結果返回給調用該程序的地方。

核心代碼實現如下,讀者可根據自身需要進行修改和優化。

package com.woniuxy.misc;import java.io.*;public class TesseractOCR {public static void main(String[] args) throws Exception { TesseractOCR ocr = new TesseractOCR(); String result = ocr.recognizeText("D:/Other/VerifyCode/1483451259840.jpg", true); System.out.println(result); }public String recognizeText(String imageFile, boolean isChinese) { String result = ""; // 保存讀取到的識別內容並返回 String tesseractExe = "C:/Tools/Tesseract-OCR/tesseract.exe"; String output = "D:/Other/VerifyResult/output"; // 根據選項組裝執行命令的字元串,注意參數之間需要加空格分隔開 String command = tesseractExe + " " + imageFile + " " + output;if (isChinese) { command += " -l chi_sim"; } System.out.println(command); // 對輸出命令進行確認,成功後該行代碼 可刪除 try { // 使用Process來獲取執行命令的結果,並對其結果進行判斷 Process process = Runtime.getRuntime().exec(command);int exeCode = process.waitFor(); // 執行的結果代碼如果為0,表示命令執行成功if (exeCode == 0) { // 讀取到輸出文件中的內容,並將其賦值給變數result InputStream fis = new FileInputStream(output + ".txt"); InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); BufferedReader br = new BufferedReader(isr); result = br.readLine(); br.close(); }else { System.out.println("本次識別操作命令未正常執行."); } }catch (Exception e) { e.printStackTrace(); }return result; }}

4. 如何實現站點驗證碼的自動識別

事實上,上述過程中我們已經將驗證碼的識別設置了自動化處理了。但是是基本文件的圖片,而通常情況下,我們要識別的驗證碼是基於網路的,所以我們需要再提前完成一件事情,利用Java代碼完成驗證碼的自動下載和保存,代碼如下:

public void download(String src, String path) {int dlstatus;try { // 發送HTTP的GET請求獲取到驗證碼圖片 URL url = new URL(src); File outFile = new File(path); HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); urlConnection.connect(); dlstatus = urlConnection.getResponseCode();if (dlstatus < 400) { // 通過位元組流讀取的方式將得到的圖片位元組碼寫入到輸出文件中 OutputStream os = new FileOutputStream(outFile); InputStream is = urlConnection.getInputStream();byte[] buff = new byte[4096];while(true) {int readed = is.read(buff);if(readed == -1) {break; }byte[] temp = new byte[readed]; System.arraycopy(buff, 0, temp, 0, readed); os.write(temp); } is.close(); os.close(); dlstatus = 200; }else { System.out.println("下載驗證碼圖片失敗,請確認."); } urlConnection.disconnect(); }catch (Exception e) { e.printStackTrace(); }}

5. 針對某個具體的站點實現自動化操作

前面的很多實驗我們已經了解了如何利用Java的協議通信API對象實現請求的發送和接收,以及處理HTTP的無狀態特性等。那麼,現在,我們不妨綜合利用前面的知識,來試著完整地完成一個有驗證碼的操作。在此,筆者不提供代碼實現,而是給大家提供一個關鍵思路:

(1)利用協議分析工具,分析驗證碼圖片的生成機制,確認是否可以將該驗證碼下載到本地。

(2)獲取到一個有效的驗證碼圖片的地址,如果圖片地址是動態生成的,則查看是否有規律可循環。

(3)利用download()方法實現對該圖片的下載。

(4)利用recognizeText()方法識別到該圖片的內容。

(5)利用sendPost()方法實現請求的發送和響應的處理。

6. 利用Java代碼去除干擾線

這是筆者在網路上收穫的一段非常有價值的代碼,在些對熱心奉獻的網友表示感謝。這段代碼通過對圖片進行像素級的處理,將一些顏色偏淡一點的背景雜色干擾線等進行了過濾,使得識別率變得更加準確。筆者親測,效果不錯。

網址為: blog.csdn.net/lmj623565

7. 如果驗證碼搞不定怎麼辦

通常情況下,我們要去識別驗證碼不一定是為了測試我們自己的項目,而是為了去干一些壞事。所以,這是大家一定要慎重的地方。我們在自己的測試項目中,如果真的出現驗證碼根本無法識別,而我們又需要繞開驗證碼,應該怎麼辦呢?方法很簡單,讓研發團隊協助我們開發一個萬能的驗證碼,或者在測試環境中取消驗證碼就好了。

思考練習

(1)如果自己正在測試的項目遇到複雜的驗證碼,應該如何處理。

(2)了解一下關於圖像處理和人工智慧方面的知識。

:學習更多技術,觀看更多免費視頻,歡迎進入蝸牛學院官網 www.woniuxy.com

希望繼續在IT行業突破提升自己的各位朋友,歡迎加群384053806,不管你自我感覺牛不牛B。

推薦閱讀:

TAG:驗證碼識別 | 軟體測試 | OCR光學字元識別 |