爬蟲(三)—— 滑動驗證碼破解

滑動驗證碼破解

1、破解步驟

1. 輸入用戶名、密碼,而後點擊登陸
2. 點擊人及識別,跳出圖片
3. 截圖,獲取完整的圖片
4. 點擊滑動按鈕,獲取破碎的圖片
5. 截圖,截取破碎的圖片
6. 完整的圖片和破碎的圖片比較,獲取移動的距離
7. 按照人的行爲行爲習慣,把總位移切成一段段小的位移
8. 按照位移移動

2、代碼實現

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By     # 按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys     # 鍵盤按鍵操做
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素
from PIL import Image   # pip3 install pillow

import time

# 截取整個屏幕圖片,保存爲snap.png
def get_snap(driver):
    driver.save_screenshot('snap.png')    # 保存整個屏幕圖片
    snap_obj=Image.open('snap.png')   # 獲取圖片對象
    return snap_obj

# 從整個屏幕的圖片中獲取驗證圖片
def get_image(driver):
    img=driver.find_element_by_class_name('geetest_canvas_img')
    time.sleep(2)   # 等待圖片加載完畢
    size=img.size
    location=img.location

    left=location['x']   # 圖片左上座標
    top=location['y']
    right=left+size['width']    # 圖片右下座標
    bottom=top+size['height']

    snap_obj=get_snap(driver)
    image_obj=snap_obj.crop((left,top,right,bottom))  # 從全屏圖中根據驗證碼圖片座標摳出驗證圖片
    # image_obj.show()    # 顯示驗證圖片
    return image_obj

# 獲取須要移動的距離
def get_distance(image1,image2):
    start_x=58    # 起始位置,缺口位置從滑塊右邊界開始查找,找到後x就是須要移動的距離
    threhold=60    # 防止干擾像素差,只有兩張圖片的像素差大於60才判斷爲
    # print(image1.size)
    # print(image2.size)
    for x in range(start_x,image1.size[0]):
        for y in range(image1.size[1]):
            rgb1=image1.load()[x,y]    # 獲取圖片的(x,y)處的RGB
            rgb2=image2.load()[x,y]
            res1=abs(rgb1[0]-rgb2[0])   # R,兩張圖片對比求出R的差值
            res2=abs(rgb1[1]-rgb2[1])   # G,兩張圖片對比求出G的差值
            res3=abs(rgb1[2]-rgb2[2])   # B,兩張圖片對比求出B的差值
            if not (res1 < threhold and res2 < threhold and res3 < threhold):
                return x-7   # 找到的x就是須要移動的距離,可是有一點偏差,減7縮小偏差

# 獲取已移動距離,要模擬人的行爲:先加速移動,再減速移動;移過了,向左移;移好以前快速抖動
def get_tracks(distance):
    distance += 20
    #v=v0+a*t
    #s=v*t+0.5*a*(t**2)

    v0=0
    s=0
    t=0.2
    mid=distance*3/5   # 設置加速減速的邊界
    forward_tracks=[]

    while s < distance:
        if s < mid:
            a = 2
        else:
            a = -3

        v=v0
        track=v*t+0.5*a*(t**2)
        track=round(track)     # 四捨五入取整
        v0=v+a*t
        s+=track
        forward_tracks.append(track)
    back_tracks=[-1,-1,-1,-2,-2,-2,-3,-3,-2,-2,-1] # 20
    return {"forward_tracks":forward_tracks,'back_tracks':back_tracks}

try:
    driver = webdriver.Chrome()
    driver.get('https://passport.cnblogs.com/user/signin')
    driver.implicitly_wait(3)

    # 一、輸入帳號、密碼,而後點擊登錄
    input_user=driver.find_element_by_id('input1')
    input_pwd=driver.find_element_by_id('input2')
    login_button=driver.find_element_by_id('signin')

    input_user.send_keys('wall-a')
    input_pwd.send_keys('lg19950726..')
    login_button.click()

    # 二、點擊按鈕,彈出沒有缺口的圖
    button=driver.find_element_by_class_name('geetest_radar_tip')
    button.click()

    # 三、針對沒有缺口的圖片進行截圖
    image1=get_image(driver)

    # 四、點擊滑動按鈕,彈出有缺口的圖
    slider_button=driver.find_element_by_class_name('geetest_slider_button')
    slider_button.click()

    #五、針對有缺口的圖片進行截圖
    image2=get_image(driver)

    # 六、對比兩張圖片,找出缺口,即滑動的位移
    distance=get_distance(image1,image2)
    # print(distance)

    # 七、按照人的行爲行爲習慣,把總位移切成一段段小的位移
    traks_dic=get_tracks(distance)

    # 八、按照位移移動
    slider_button=driver.find_element_by_class_name('geetest_slider_button')
    ActionChains(driver).click_and_hold(slider_button).perform()  # 能夠sleep幾秒,更真實
    # 先向前移動
    forward_tracks=traks_dic["forward_tracks"]
    back_tracks=traks_dic["back_tracks"]
    for forward_track in forward_tracks:
        ActionChains(driver).move_by_offset(xoffset=forward_track,yoffset=0).perform()

    # 短暫停頓,移過了
    time.sleep(0.2)

    # 先向後移動
    for back_track in back_tracks:
        ActionChains(driver).move_by_offset(xoffset=back_track,yoffset=0).perform()

    ActionChains(driver).move_by_offset(xoffset=-3,yoffset=0).perform()
    ActionChains(driver).move_by_offset(xoffset=3,yoffset=0).perform()
    time.sleep(0.3)
    ActionChains(driver).release().perform()


    time.sleep(10)
finally:
    driver.close()
相關文章
相關標籤/搜索