驗證碼破解一

簡介

爬蟲在抓網站數據時,不可避免要和驗證碼做長久鬥爭。當然能繞過最好,但是總有繞不過的驗證碼,此時,對於簡單的可以嘗試破解,有難度的對接打碼平臺。現在驗證碼多種多樣,點選,滑動,英文字母組合等,接下來簡單的聊一聊英文字母組合中的這兩種驗證碼的破解。

               

流程

識別英文字母組合驗證碼的一般步驟通常是:加載圖片,灰度化,二值化,去除噪點(包括干擾線),字符分割,訓練模型,識別。其中的難點一般在去燥和字符分割這兩步,比如搜狗微信的驗證碼干擾線比字符還要粗,去燥不可避免會傷及字符,比如百度驗證碼粘連,扭曲,變形。這種驗證碼不需要去除噪點,單恰恰是特別難的,分割特別麻煩,當然要是你能生成各種類型的驗證碼,那驗證碼的破解就非常easy了,只需要將帶有標籤的大批量驗證碼通過神經網絡CNN訓練出模型,可以高精度識別。

驗證碼處理一般需要使用PIL,opencv這兩個模塊。這裏我們主要使用PIL庫,驗證碼的處理主要是對圖片的像素點進行操作,彩色圖像中的每個像素的顏色有RGB三個分量決定,而灰度圖像是RGB三個分量相同的一種特殊的彩色圖像,將圖片進行灰度化可以通過這兩種方式實現。

              1:像素點的RGB三色求平均

              2:R * 0.3+ G * 0.59 +B * 0.11

二值化是通過閥值將像素點轉化成非白(255)即黑(0)的值

具體代碼實現:

# 加載圖片
img = Image.open('0.jpg')
# 圖片轉化爲灰色圖片
img = img.convert("L")  
# 圖片灰度化
pixdata = img.load()
for y in range(img.size[1]):
    for x in range(img.size[0]):
        if x <= 5 or x >= 195 or y <= 5 or y >= 47:
            pixdata[x, y] = 225
        if pixdata[x, y] < 100:
            pixdata[x, y] = 0
        else:
            pixdata[x, y] = 255

這兩步處理之後圖片變爲,

圖片去除噪點有很多種方法,濾波法,鄰域法,輪廓法等,這裏通過8鄰域法實現,主要是控制好閥值避免誤傷,當一次效果理想時,可以適當增加降噪次數。

def denoising(im):
    """圖片去除噪點"""
    pixdata = im.load()
    w, h = im.size
    for j in range(1, h - 1):

        for i in range(1, w - 1):
            count = 0
            l = pixdata[i, j]
            if l == pixdata[i, j - 1]:
                count = count + 1
            if l == pixdata[i, j + 1]:
                count = count + 1
            if l == pixdata[i + 1, j - 1]:
                count = count + 1
            if l == pixdata[i + 1, j + 1]:
                count = count + 1
            if l == pixdata[i + 1, j]:
                count = count + 1
            if l == pixdata[i - 1, j + 1]:
                count = count + 1
            if l == pixdata[i - 1, j - 1]:
                count = count + 1
            if l == pixdata[i - 1, j]:
                count = count + 1
            if count < 4:
                pixdata[i, j] = 255

    return im

去燥之後的圖片已經基本不影響分割和識別了

驗證碼分割一樣有很多中針對特定情形的方法。圖形基本不粘連的垂直陰影法,cfs通道法,以及稍稍粘連使用滴水算法切割等

效果都特別好。博主對這種明顯不粘連的驗證碼才用的是垂直陰影法切割

# 垂直陰影法分割
def get_projection_x(image, invert=False):
    p_x = [0 for x in range(image.size[0])]
    for w in range(image.size[1]):
        for h in range(image.size[0]):
            if invert:
                if image.getpixel((h, w)) >= 200:
                    p_x[h] += 1
                    continue
            else:
                if image.getpixel((h, w)) <= 5:
                    p_x[h] += 1
                    continue
    # 判斷邊界
    l, r = 0, 0
    flag = False
    cuts = []
    for i, int in enumerate(p_x):
        # 閾值這裏爲2
        if flag is False and int > 3:
            l = i
            flag = True
        if flag and int <= 3:
            r = i - 1
            flag = False
            cuts.append((l, r))
    return cuts

分割之後得到的單個字符,雖然祛噪點並不是特別完美,採用神經網絡或者支持向量機訓練模型並不大影響識別效果,但是打標籤的過程並不享受。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章