1. 程式人生 > >nodeJS實現識別驗證碼(tesseract-ocr+GraphicsMagick)

nodeJS實現識別驗證碼(tesseract-ocr+GraphicsMagick)

背景

最近在寫一個爬蟲的小工具,卡在登入這裡。

想爬的網站需要登入才能獲取資料,登入又需要輸入驗證碼。

好在驗證碼是簡單的驗證碼,還可以自己識別試試。

 

需求分析

1、儲存驗證碼圖片

2、識別驗證碼

3、對識別的驗證碼進行人工校準

 

功能實現

1、儲存驗證碼圖片

雖然每個網站不一定一樣,但是大體的思路是差不多的,我要爬取的網站是後臺返回了一個驗證碼圖片和cookie,所以我們需要把這兩個東西都存下來。

這裡用到了node中的request模組,具體沒什麼好說的,請求後獲取response中的set-cookie,然後再把圖片流存下來。request文件

        let cookie = "";
let options = { url: "" headers: { Accept: "*/*", "Accept-Encoding": "utf-8", "Accept-Language": "zh-CN,zh;q=0.8", Connection: "keep-alive",'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',//偽裝瀏覽器 }, method: 'GET', }; let stream = fs.createWriteStream("./code.jpg"); request(options, function (error, response) { cookie = response.headers["set-cookie"]; }).pipe(stream).on('close', function () { console.log(cookie); });

 

2、識別驗證碼

識別驗證碼需要用到兩個工具一個是GraphicsMagick,另一個是tesseract-ocr。

2.1 安裝工具

在找資料的時候看到很多部落格都只寫了node安裝他們的wrapper工具,都沒有寫清楚,實際上這兩個工具我們都要自行安裝,安裝包網上找就ok。

GraphicsMagick安裝完後需要修改環境變數,在path中新增安裝目錄的地址,比如我安裝在D盤,就新增D盤的路徑。

需要注意的是,小寫的分號  ;   不要忘記了

完成後輸入在命令列輸入gm,能出現如下資訊就說明安裝好了

 

tesseract-ocr安裝完後也需要修改環境變數,操作和GraphicsMagick一樣,然後需要多新增一個環境變數TESSDATA_PREFIX,變數值是你按照目錄下的tessdata

 

完成後輸入在命令列輸入tesseract,能出現如下資訊就說明安裝好了

 

2.2安裝node下的wrapper工具

GraphicsMagick 安裝gm,直接npm install gm 就可以安裝

tesseract-ocr安裝tesseractocr,也是npm install tesseractocr就可以安裝

需要注意的是:找資料的時候發現很多人安裝的都是node-tesseract,我在使用的時候一直報-psm這個選項錯誤,後來去github倉庫上面找issue,發現也有人遇到這個問題,原因是我們安裝的tesseract是最新的,-psm這個選項已經改成了--psm,所以一直報錯。找了一圈也沒找到解決辦法,所以只好換個包來用。於是在npm的倉庫裡面找到了tesseractocr這個包。

他的Last publish是一年前,所以就拿來試一試,果然能用。畢竟node-tesseract是5 years ago。。。。

 

2.3 處理圖片為閾值圖片

用threshold方法來處理圖片,文件的解釋是:

Modify the image such that any pixel sample with an intensity value greater than the threshold is assigned the maximum intensity (white), or otherwise is assigned the minimum intensity (black).

說白了就是把圖片處理成黑白的,去掉一些噪點線條,因為有噪點線條存在的話,tesseract的識別率會很低,然後閾值預設是55,但是在我的圖片上55的閾值丟失的資訊太多,所以我就放大了一些。

這裡我還用了resize把圖片放大一些,因為我在實際操作時發現,很多次識別都報了empty page這個錯誤,查閱資料發現是由於圖片解析度太小導致的,所以就顯式地放大了圖片。

        gm(imgPath)
            .threshold(thresholdVal || 160)
            .resize(200, 100)
            .write(newPath, (err) => {
                if (err) return reject(err);
                resolve(newPath);
            });

 

2.4 識別圖片

直接呼叫tesseract來識別圖片中的內容,最後將識別出來的內容去空

var recognizer = function (imgPath) {
    return new Promise((resolve, reject) => {
        recognize(imgPath, (err, text) => {
            if (err)
                throw err;
            else
                resolve(text.replace(/[\r\n\s]/gm, ''));
        });
    })
};

 

3、對識別的驗證碼進行人工校準

沒有訓練過的tesseract其實識別率很低,所以要加一個人工校準的操作,讓我們輸入的驗證碼準確率能高一些。

這裡用了readline-sync模組獲得使用者的命令列輸入。

        recognizer()
            .then(text => {
                console.log(`識別結果:${text}`);
                code = text;
                let res = readlineSync.question('是否使用?: ');
                if (res.toLowerCase() === 'n') {
                    code = readlineSync.question('請輸入實際值?: ');
                }
                console.log(code);
            })

 

總結

看看最終效果

識別率雖然不高,但是也有識別正確的,然後也把登入的部分cookie打印出來了,可以說是基本完成了需