爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

首先,我對驗證碼做了初步的觀察分析。總結如下:

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

驗證碼中的字符位數始終為6位,並且是灰度圖像;

字符之間的間隔看起來始終保持相同的間隔;

每個字符都是完全定義的;

圖像有許多雜散的暗像素,以及穿過圖像的線條

我決定下載一個圖片驗證碼,並藉助 這款工具 以二進制可視化圖像(0表示黑色,1表示白色像素)。

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

我的觀察是正確的 – 圖像尺寸為45×180,每個字符被分配一個30像素的空間來擬合,從而使它們均勻間隔。

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

我將其包裝在一個循環中,寫了一個簡單的腳本,從該站點獲取500個驗證碼圖像,並將所有裁剪後的字符保存到一個文件夾中。

第三次觀察 – 每個字符都有明確的定義。為了“清理”圖像中的裁剪字符(刪除不必要的線和點),我使用了以下方法。

字符中的所有像素都是純黑色(0)。我用了一個簡單的邏輯 – 如果它不是完全黑色的,就視為白色。因此,對於值大於0的每個像素,將其重新分配為255。使用load()函數將圖像轉換為45×180矩陣,然後對其進行處理。

pixel_matrix = cropped_image.load()for col in range(0, cropped_image.height): for row in range(0, cropped_image.width): if pixel_matrix[row, col] != 0: pixel_matrix[row, col] = 255image.save("thresholded_image.png")

為了更加清晰,我將代碼應用至原始圖像上。

原圖:

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

處理後:

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

可以看到處理後的圖像中的非純黑像素都已被移除,其中包括穿插圖像的線條。

直到項目完成後,我才知道上述方法被稱為圖像處理中的閾值處理。

第四次觀察 – 圖像中有許多雜散像素。

循環遍歷圖像矩陣,如果相鄰像素為白色,與相鄰像素相對的像素也為白色,且中心像素為黑色的,則使中心像素為白色。

for column in range(1, image.height - 1): for row in range(1, image.width - 1): if pixel_matrix[row, column] == 0 \ and pixel_matrix[row, column - 1] == 255 and pixel_matrix[row, column + 1] == 255 : pixel_matrix[row, column] = 255 if pixel_matrix[row, column] == 0 \ and pixel_matrix[row - 1, column] == 255 and pixel_matrix[row + 1, column] == 255: pixel_matrix[row, column] = 255
爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

一個將按照字符排序的相似圖像分組(約束條件:暗像素數量,相似度>= 90 – 95 %)

一個從每個分組字符中獲得最佳圖像

因此現在已生成了庫圖像。將它們轉換為像素矩陣,並將“位圖”存儲為JSON文件。

最後,這是解決任何新的驗證碼圖像的算法。

使用相同的算法減少新圖像中不必要的干擾

對於新驗證碼圖像中的每個字符,通過我生成的JSON位圖強制執行。根據對應的暗像素匹配來計算相似度。

這意味著,如果一個像素為暗像素,在圖像中的位置為(4,8),並且如果該像素在我們的骨架圖像/位圖中的相同位置處為暗像素,則計數值會遞增1。

該計數與骨架圖像中暗像素的數量相比,用於計算百分比匹配。

選擇匹配率最高的字符。

import json characters = "123456789abcdefghijklmnpqrstuvwxyz" captcha = "" with open("bitmaps.json", "r") as f: bitmap = json.load(f) for j in range(image.width/6, image.width + 1, image.width/6): character_image = image.crop((j - 30, 12, j, 44)) character_matrix = character_image.load() matches = {} for char in characters: match = 0 black = 0 bitmap_matrix = bitmap[char] for y in range(0, 32): for x in range(0, 30): if character_matrix[x, y] == bitmap_matrix[y][x] and bitmap_matrix[y][x] == 0: match += 1 if bitmap_matrix[y][x] == 0: black += 1 perc = float(match) / float(black) matches.update({perc: char[0].upper()}) try: captcha += matches[max(matches.keys())] except ValueError: print("failed captcha") captcha += "0" print captcha 

最終得到的結果如下:

爬蟲驗證碼很難嗎?自動識別驗證碼程序瞭解一下?

可以看到驗證碼被成功識別為Z5M3MQ!

總結

這個項目對於我本人而言,也是一次非常好的學習經歷。我還開發了一個 Chrome插件 ,目前有1800+的用戶,歡迎大家安裝使用!此外,如果你有任何的意見和建議也歡迎向我提出。以上的代碼我已託管在GitHub,你可以

在這裡找到


分享到:


相關文章: