python + selenium 爬蟲模擬登錄破解無原圖滑動驗證碼


爬蟲模擬登錄破解無原圖滑動驗證碼: https://www.cnblogs.com/98WDJ/p/11050559.html

需求:部分網站在頻繁的使用之后,會彈出滑塊驗證碼(極驗)。有別於過去,現在的原圖並不會出現,因此較過去的思路轉變為以下:

1、截取帶缺口的圖片;

2、尋找原圖,並截圖;

3、比較兩張圖片,尋找到缺口位置距離;

4、計算運動過程,並驅動瀏覽器移動滑塊。

參考鏈接基本提供了1-3步的實現,第4步存在被識別為機器操作,需要進行更新(修正以后,目前成功率應該有50%以上),記錄如下。

一、啟動瀏覽器,配置option,以防被識別為自動化。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import ActionChains
from PIL import Image
import numpy as np
import pandas as pd
import time

# 配置瀏覽器
options = webdriver.ChromeOptions()
# 此步驟很重要,設置為開發者模式,防止被各大網站識別出來使用了Selenium
options.add_experimental_option('excludeSwitches', ['enable-automation']) 

二、獲取兩張圖片進行比較,通過網頁分析發現。該標簽,當display=block,opacity=1時,顯示的為原圖。

# 獲取第一個圖
img_name1 = r'../data/png/captcha2.png'
img_name2 = r'../data/png/captcha2_src.png'
img = wait.until(EC.presence_of_element_located((By.XPATH,'//canvas[@class="geetest_canvas_slice geetest_absolute"]')))
img.screenshot(img_name1)

# 獲取原圖
browser.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];"
                          "x.style.display='block';"
                          "x.style.opacity=1"
                          )
img = wait.until(EC.presence_of_element_located((By.XPATH,'//canvas[@class="geetest_canvas_slice geetest_absolute"]')))
img.screenshot(img_name2)
# 變回來
browser.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];"
                          "x.style.display='none';"
                          "x.style.opacity=0"
                          )

三、計算兩張圖片差異,通過rgb一定的缺值進行判斷缺口。

# 如何能找到滑塊的位置
def get_distance(img1,img2):
    start_x=60#初始X
    threhold=60#閾值
    for x in range(start_x,img1.size[0]):
        for y in range(img1.size[1]):
            rgb1=img1.load()[x,y]
            rgb2=img2.load()[x,y]
            res1=abs(rgb1[0]-rgb2[0])
            res2=abs(rgb1[1]-rgb2[1])
            res3=abs(rgb1[2]-rgb2[2])
            if not (res1<threhold and res2<threhold and res3<threhold):
                return x-7#測試后-7可以提高成功率

四、計算模擬移動,根據自身的挪動特點,我一般的移動操作分為三個階段(可根據自身特點進行設計)。

1:點擊滑塊以后,緩慢移動一下。約移動3次。

2:快速移動到缺口附件。大概0.3s。

3:到了缺口附近以后,緩慢靠近,然后在缺口處停留大概0.5秒以后釋放。

# 將整個過程分為3段,總時長大概是1.2-1.6秒
# 第一段是啟動階段,第一次點擊的時候,總會比較拘謹,慢速啟動,大概消費t2(0.3)秒,s2為分段數
# 第二段則是很快到達缺口附近,大概剩余d3(5)距離處
# 第三段是緩慢對接,最后停在上面0.5秒
def get_tracks(distance,s1 = 2,t2 = 0.3,s2 = 3,d3 = 5):
    # 計算d1移動過程
    dtemp = 0
    track1 = []
    for i in range(s1):
        t = np.random.randint(low = 1, high=3)
        track1.append(t)
        dtemp = dtemp + t
    
    # 計算d2距離
    distance =distance - dtemp - d3
    
    track2 = []
    a = 2 * distance /(t2 ** 2)
    dtemp = 0
    for i in range(s2):
        # 計算每段行走
        ttemp1 = t2/s2 * (i + 1)
        ttemp2 = t2/s2 * i
        t = int(0.5 * a * (ttemp1 ** 2) - 0.5 * a * (ttemp2 ** 2) )
        track2.append(t)
        dtemp = dtemp + t
        
    #由於取整了,可以存在一點誤差,調整d3
    d3 = distance - dtemp + d3
    print(d3)
    track3 = []
    s = 0
    while s < d3:
        t = np.random.randint(low = 1, high=3)
        if s + t >= d3:
            track3.append(d3 - s)
            break
        else:
            s = s + t
            track3.append(t)    
    return {"track1": track1, 'track2': track2, 'track3': track3}
%%time
# 計算路徑,不行,這個會被識別為計算機
#獲得滑塊元素
geetest_slider_button=browser.find_element_by_class_name('geetest_slider_button')
#獲得距離
img1 = Image.open(img_name1)
img2 = Image.open(img_name2)
distance=get_distance(img1,img2)
#獲得步數
tracks_dic=get_tracks(distance,s1 = 2,t2 = 0.2,s2 = 3,d3 = 5)
#點擊並按住    ActionChains(driver).click_and_hold(geetest_slider_button).perform()
track1=tracks_dic['track1']
track2=tracks_dic['track2']
track3=tracks_dic['track3']

最后,遍歷執行動作鏈。

%%time
# 執行
ActionChains(browser).click_and_hold(geetest_slider_button).perform()
# 執行第一步
for t in track1:
    ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform()
#停頓一會,更像人
time.sleep(0.2)
for t in track2:
    ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform()
for t in track3:
    ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform()
time.sleep(0.5)
# 松開
ActionChains(browser).release(geetest_slider_button).perform()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM