聊聊滑塊驗證碼的識別

很長一段時間沒寫文章了,今天來一篇,聊聊滑塊驗證碼。之前一段時間在研究下滑塊驗證碼相關的東西,拿騰訊的驗證碼來玩,使用Selenium來模擬滑動,這裏也就先不介紹Selenium 的基本用法來,主要來聊聊怎麼實現滑塊驗證碼的識別問題。
滑塊驗證碼可以說是目前使用最多,體驗相對比較好的驗證方式來,在反爬蟲上面也確實有比較好的效果,但爬蟲和反爬蟲,本身就是一對冤家,相互促進項目影響。廢話不多說,直接上滑塊驗證碼的乾貨吧。

一、目標

就拿騰訊的滑塊驗證碼來說吧,其他滑塊也比較類似,就這個:
QQ滑塊
先大概梳理一下這個特徵,點擊驗證,彈出這個滑塊驗證碼,用鼠標拖動到缺口陰影位置鬆手即可實現驗證。
邏輯比較簡單,目前要處理的核心問題就是怎麼找到這個陰影位置,因爲可能有不同的圖片而且圖片中缺口陰影的位置也不確定。
問題可以簡化爲:如何找到背景圖中缺口的準確位置

二、查找缺口陰影位置

定下了解決問題的目標,下一步就是查找當前的已知條件,看看已知條件能否找到突破口,目前我們可以確定的是,如果要用滑塊驗證碼,至少要有兩樣東西:

  1. 滑動的滑塊圖形,就是這個:

滑塊圖

  1. 滑動要拼出的背景圖,就是這個:

背景圖

這兩個傢伙是每個滑塊都有的東西,先從這兩個上面入手:

先試着處理下背景圖,這裏用python來寫了:

from PIL import Image
if __name__ == "__main__":
    Image.open('hycdn_1_1585354975542067968_0.jpeg').convert('L').save('cap4.jpg')

我們將這個背景圖片置成灰色圖片看看,現在是這個樣子:
置成灰色圖片
現在這個背景圖沒有其他雜色了,再看這個缺口位置,顏色要更深一點,那接下來就處理下滑塊了,讓它儘量和這個缺口相似:

def convert(imgName, saveName):
    im = Image.open(imgName)
    im = im.convert('RGBA')

    width = im.size[0]
    height = im.size[1]
    for h in range(0, height):
        for w in range(0, width):
            pixel = im.getpixel((w, h))
            if pixel[0] > 0 and pixel[1] > 0 and pixel[2] > 0 and pixel[3] > 0:
                im.putpixel((w, h), (0,0,0, 220))
            elif pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0:
                im.putpixel((w, h), (0, 0, 0, 220))
            else:
                pass
    im.save(saveName)

convert('hycdn_2_1585354975542067968_0.png','cap2.png')

將整張滑塊圖進行像素調節,這個調節值是反覆試出來的,出來的效果是這樣:
處理後滑塊
這樣處理後,我們要做的其實就剩下最後一步了:從這個背景圖中找出和這個滑塊最相似的圖形並標記出來

這裏使用了一個開源庫aircv,Github上地址是https://github.com/NetEaseGame/aircv,大概使用方式是這個:

import aircv as ac
imsrc = ac.imread('youimage.png') # 原始圖像
imsch = ac.imread('searched.png') # 帶查找的部分
ac.find_template(imsrc, imsch)
#返回值
#{'confidence': 0.5522063970565796, 'result': (557, 214), 'rectangle': ((489, 146), (489, 282), (625, 146), (625, 282))}
# result: 查找到的點
# rectangle: 目標圖像周圍四個點的座標
# confidence: 查找圖片匹配成功的特徵點 除以 總的特徵點

從圖形中查找相似部分,詳細使用可以查看Github。
我們這樣處理一下:

    imsrc = ac.imread('cap4.jpg')
    imobj = ac.imread('cap2.png')

    # find the match position
    pos = ac.find_template(imsrc, imobj)

    print pos
    # {'confidence': 0.5522063970565796, 'result': (557, 214), 'rectangle': ((489, 146), (489, 282), (625, 146), (625, 282))}

    color = (0, 255, 0)
    line_width = 10

    draw_rectangle(imsrc, pos['rectangle'][0], pos['rectangle'][-1], color, line_width)

python-opencv2繪製一下區域看看:

import cv2
def draw_rectangle(img, pos1, pos2, color, line_width):
    cv2.rectangle(img, pos1, pos2, color, line_width)
    cv2.imshow('objDetect', imsrc)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

好啦,我們看下效果:
成功命中
再試幾個看看:

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