驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

Adrian沒有訪問生成驗證碼圖片的應用的源代碼的權限。為了破解這個系統,他不得不下載成百上千個示例圖像並手動解答它們,用以訓練他的深度學習系統。

但是如果我們想打破一個開放源代碼的驗證碼系統,將會怎麼樣?

我去http://wordpress.org插件註冊表搜索“驗證碼”。最靠前的結果是一個叫“真正簡單的驗證碼”的插件,有超過100萬個活躍安裝:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

好的,所以驗證碼圖像似乎是四個字母。讓我們在PHP源代碼中驗證這一點:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

是的,它會產生一個四字母的驗證碼,並採用隨機組合的四種不同的字體。我們可以看到,它從不在代碼中使用“O”或“I”,以避免用戶混淆。這給了我們總共32個可能需要識別的字母和數字。沒問題!

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

TensorFlow

TensorFlow是谷歌的機器學習庫。我們會在Keras中寫代碼,但Keras並沒有真正實現神經網絡的邏輯本身,它其實是在後臺調用谷歌的TensorFlow進行計算。

好,現在讓我們回到挑戰!

創造我們的數據集

訓練任何機器學習系統,我們都需要訓練數據集。破解一個驗證碼系統,我們則需要訓練數據看起來像這樣:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

由於我們有這個WordPress的驗證碼插件的源代碼,我們可以對它做一些更改,讓它保存出10000張驗證碼圖像以及每個圖像的正確答案。

花了幾分鐘時間,在適當地修改源代碼並添加一個簡單的for後,我得到了一個包含訓練數據的文件夾 —— 10000個PNG文件,每個文件都以正確答案作為文件名:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

這是唯一我不會給你示例代碼的部分。我們這樣做是為了教育,我不想讓你真的去黑WordPress網站。不過,我會給你我最後生成的這10000張圖像,以便你可以重複我的結果。

到目前為止時間過去:5分鐘。

簡化問題

現在我們有了訓練數據,我們可以直接用它來訓練神經網絡:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

有足夠的訓練數據,這種粗暴的方法甚至也行得通 - 但我們可以使問題更容易解決。問題越簡單,訓練數據越少,計算資源消耗就越少。畢竟我們只有15分鐘!

幸運的是,驗證碼圖像總是由四個字母組成。如果我們能用某種方式把圖像分割開來,這樣每一個字母都是一個獨立的圖像,那麼我們只需要訓練神經網絡一次識別一個字母:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

我沒有時間瀏覽10000個訓練圖像,並在Photoshop中手動將它們分割成單獨的圖像。這將需要幾天,而我只剩下10分鐘了。

而且我們不能將圖像分成四個相同大小的塊,因為驗證碼會將這些字母隨機放置在不同的水平位置:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

每個圖像中的字母隨機放置,使分割圖像更難一些。

幸運的是,我們仍然可以自動執行此操作。在圖像處理中,我們經常需要檢測具有相同顏色的像素團。這些連續像素團周圍的邊界被稱為輪廓。OpenCV有一個內置的findContours()函數,可以用來檢測這些連續的區域。

那麼我們將從一個原始的驗證碼圖像開始:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

然後,我們將圖像轉換為純黑白(這稱為閾值設定),這樣就很容易找到連續的區域:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

接下來,我們將使用OpenCV的findContours()函數來檢測圖像中各個包含相同顏色像素的連續團:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

那麼只需將每個區域保存為一個單獨的圖像文件即可。而且由於我們知道每個圖像應該包含從左到右的四個字母,所以我們可以使用這些知識來標記字母。只要我們按順序保存它們,我們能夠用適當的字母名稱保存每個字母圖像。

但是等等 —— 我看到一個問題! 有時候驗證碼有這樣的重疊字母:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

這意味著我們最終將提取將兩個字母拼湊在一起的區域:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

如果我們不處理這個問題,我們最終會創建糟糕的訓練數據。我們需要解決這個問題,以免我們不小心讓機器把這兩個相連的字母識別為一個字母。

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

我們將把任何寬度比高度還長的區域對半分開,並把它當作兩個字母。這是很粗暴,但這麼處理對識別這些驗證碼依然行得通。

現在我們有了一種提取單個字母的方法,讓我們在所有的CAPTCHA圖像上運行它。目標是收集每個字母的不同變化。我們可以將每個字母保存在自己的文件夾中。

下面是我提取所有字母后,我的“W”文件夾的樣子:

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

從我們的10000個驗證碼圖像中提取的一些“W”字母。我一共得到了1147個不同的“W”圖像。到目前為止時間過去:10分鐘。

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

現在,我們可以開始訓練它了!

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

用訓練數據集訓練10次後,我們達到了近100%的準確度。現在,只要我們想,我們應該能夠自動繞過這個驗證碼了!我們做到了!

到目前為止時間過去:15分鐘。(~!)

使用訓練的模型破解驗證碼

現在,我們有一個訓練有素的神經網絡,用它來破解真正的驗證碼非常簡單:

1.從使用該WordPress插件的網站抓取真實的驗證碼圖像。

2.使用我們用來創建訓練數據集的相同方法,將驗證碼圖像分解為四個單獨的字母圖像。

3.要求我們的神經網絡對每個字母圖像做一個單獨的預測。

4.使用四個預測字母作為驗證碼的答案。

5.愉快的玩耍吧

以下是我們的模型如何解碼真正的驗證碼

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

或者從命令行

驗證碼是爬蟲非常頭疼的問題!今天通過十五分鐘就教你搞定驗證碼

試試看吧!

如果你想親自嘗試一下,你可以在這裡獲取代碼。它包括10000個示例圖像和本文中每個步驟的所有代碼。查看裡面的README.md文件,瞭解如何運行它。

但是,如果你想了解每一行代碼究竟做了什麼,我強烈建議你也弄一本《Python計算機視覺深度學習》。它有更多的細節,並有大量的詳細的例子。這是迄今為止我所見過的唯一的一本,既涵蓋了工作原理又涵蓋了在現實世界中如何解決難題的書。去看看吧!


分享到:


相關文章: