selenium+opencv幹掉滑動驗證碼

我們在用自動化測試來做爬蟲的時候,總是會遇見很多的驗證碼,其中的滑塊拼接驗證就是其中一種;selenium是一個自動化測試庫,opencv是計算機視覺庫,我們可以用這兩個庫來模仿人工滑動驗證碼,完成驗證碼驗證操作!

目標網站: http://dun.163.com/trial/sense
完成對象:
在這裏插入圖片描述

操作流程:

1、找到目標

  • 這裏我們需要使用selenium庫來模擬操作瀏覽器,可以通過pip install selenium安裝它,同時需要下載對應瀏覽器版本的webdriver來輔助控制電腦,這裏就不詳細講解了,直接看操作流程:
from selenium import webdriver
import time

#創建瀏覽器
driver = webdriver.Chrome()

#輸入網址,打開該網站
driver.get('http://dun.163.com/trial/sense')

#點擊網頁
#1、點擊選擇“可疑用戶-滑動拼圖”
driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/ul/li[2]').click()
time.sleep(1)#等待加載
#2、點擊驗證碼位置“請完成安全驗證”
driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[1]/div[1]/span').click()
  • 通過上面的流程找到驗證碼的位置,開始獲取驗證碼圖片

2、下載驗證碼圖片

  • 從網頁中,我們可以看出這是兩張圖片:
    在這裏插入圖片描述
  • 現在需要把這兩張圖片下載到本地文件
    #獲取到兩張圖片鏈接
    bg_img_scr = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[1]/div/div[1]/img[1]').get_attribute('src')
    front_img_src = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[1]/div/div[1]/img[2]').get_attribute('src')

    #把圖片下載到本地
    with open('./bg.jpg',mode='wb') as f:
        f.write(requests.get(bg_img_scr).content)
        f.close()
    with open('./front.jpg',mode='wb') as f:
        f.write(requests.get(front_img_src).content)
        f.close()

3、識別圖像戳口

3.1、讀取本地圖片並展示

  • 這裏包含三個部分,分別爲:讀取,展示,釋放,缺一不可。
import cv2
#讀取圖片
bg = cv2.imread('./bg.jpg')
front = cv2.imread('./front.jpg')

#展示圖片
cv2.imshow('gray1',bg)#gray1,gray2是窗口名稱
cv2.imshow('gray2',front)

#釋放資源
cv2.waitKey(0)#按任意鍵退出圖片展示
cv2.destroyAllWindows()

展示結果:
在這裏插入圖片描述

3.2、圖片灰度處理

  • 圖片灰度處理的目的是讓顏色方差更明顯
#灰度處理
bg = cv2.cvtColor(bg,cv2.COLOR_BGR2GRAY)
front = cv2.cvtColor(front,cv2.COLOR_BGR2GRAY)

在這裏插入圖片描述

3.3、去掉滑塊黑色部分

  • 目的是爲了和背景圖片進行匹配
front = front[front.any(1)]#0表示黑色,1表示高亮部分

在這裏插入圖片描述

3.4、識別圖像位置

  • 通過這個算法,圖像從左上角開始匹配,進行像素點對比,並記錄每個像素點的數值,以多維數組的方式返回
  • 通過numpy將數組變爲一維數組,索引出最大值的位置。
import numpy as np
#匹配->cv圖像匹配算法
result = cv2.matchTemplate(bg, front, cv2.TM_CCOEFF_NORMED)#match匹配,Template模板;精度高,速度慢的方法
index_max = np.argmax(result)#返回的是一維的位置,最大值索引
  • 根據一維數組的位置反推出二維數組中的位置。
#反着推最大值的二維位置,和opencv是相反的
x, y = np.unravel_index(index_max, result.shape)
print ("二維中座標的位置:",x, y)
二維中座標的位置: 79 145
  • 這個位置就是戳口的位置

注意: opencv的座標與座標軸的是相反的。


4、拖動滑塊

4.1、控制滑塊滑動

from selenium.webdriver.common.action_chains import ActionChains
drop = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[2]/div[2]')    
ActionChains(driver).drag_and_drop_by_offset(drop, xoffset=y, yoffset=0).perform()

4.2、驗證是否滑動成功

  • 當驗證通過後,滑動底的部會出現“驗證成功”,如圖:
    在這裏插入圖片描述
  • 可以通過檢查這個文字判斷是否驗證成功,如果第一次驗證失敗,可以繼續驗證,直到成功爲止!
    success = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[1]/div[2]/span[2]').text
    if success == '驗證成功':            
        break
    else:
        print ('第%s次驗證失敗...'%k,'\n')

代碼彙總:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time,requests
import cv2
import numpy as np

#創建瀏覽器
driver = webdriver.Chrome()

#輸入網址,打開該網站
driver.get('http://dun.163.com/trial/sense')

#點擊網頁
driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/ul/li[2]').click()
time.sleep(1)
driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[1]/div[1]/span').click()
time.sleep(1)

k = 1
while True:
    #獲取到兩張圖片鏈接
    bg_img_scr = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[1]/div/div[1]/img[1]').get_attribute('src')
    front_img_src = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[1]/div/div[1]/img[2]').get_attribute('src')

    #把圖片下載到本地
    with open('./bg.jpg',mode='wb') as f:
        f.write(requests.get(bg_img_scr).content)
        f.close()
    with open('./front.jpg',mode='wb') as f:
        f.write(requests.get(front_img_src).content)
        f.close()

    #讀取圖片
    bg = cv2.imread('./bg.jpg')
    front = cv2.imread('./front.jpg')

    #灰度處理
    bg = cv2.cvtColor(bg,cv2.COLOR_BGR2GRAY)
    front = cv2.cvtColor(front,cv2.COLOR_BGR2GRAY)

    #去掉滑塊黑色部分
    front = front[front.any(1)]#0表示黑色,1表示高亮部分

    #匹配->cv圖像匹配算法
    result = cv2.matchTemplate(bg, front, cv2.TM_CCOEFF_NORMED)#match匹配,Template模板;精度高,速度慢的方法
    index_max = np.argmax(result)#返回的是一維的位置,最大值索引

    #反着推最大值的二維位置,和opencv是相反的
    x, y = np.unravel_index(index_max, result.shape)
    print ("二維中座標的位置:",x, y)
    print ("正在進行第%s次滑動驗證"%k)
    drop = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[2]/div[2]')    
    ActionChains(driver).drag_and_drop_by_offset(drop, xoffset=y, yoffset=0).perform()
    time.sleep(1)
    
    #驗證成功後獲取“驗證成功”,直到找到“驗證成功”才跳出while True循環
    success = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[1]/div[2]/span[2]').text
    if success == '驗證成功':            
        break
    else:
        print ('第%s次驗證失敗...'%k,'\n')
    k = k + 1
print ('已經通過驗證碼!!!') 

運行結果:

二維中座標的位置: 50 258
正在進行第1次滑動驗證
第1次驗證失敗... 

二維中座標的位置: 79 145
正在進行第2次滑動驗證
已經通過驗證碼!!!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章