python selenium爬蟲滑塊驗證


思路:

1、獲取帶滑塊的圖片

2、獲取不帶滑塊、完整的圖片

3、比較兩張圖片中不一樣的地方,找到滑塊的坐標

4、通過滑塊坐標來拖動瀏覽器

代碼:

import random
import time
from PIL import Image
from io import BytesIO

import requests as rq
from bs4 import BeautifulSoup as bs

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver import ChromeOptions


def crop_image(image_file_name):  
    # 保存圖片
    # 截圖驗證碼圖片
    # 定位某個元素在瀏覽器中的位置
    time.sleep(2)
    img = browser.find_element_by_xpath("//*[@class='geetest_canvas_slice geetest_absolute']")
    location = img.location
    print("圖片的位置", location)
    size = img.size
    top, buttom, left, right = location["y"], location["y"]+size["height"], location["x"], location['x'] + size["width"]
    print("驗證碼位置", left,top, right, buttom)
    screenshot = browser.get_screenshot_as_png()
    screenshot = Image.open(BytesIO(screenshot))
    captcha = screenshot.crop((int(left),int(top), int(right), int(buttom)))
    captcha.save(image_file_name)
    return captcha


def compare_pixel(image1, image2, i, j):
    # 判斷兩個圖片像素是否相同
    pixel1 = image1.load()[i, j]
    pixel2 = image2.load()[i, j]
    
    threshold = 60
    if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(pixel1[2] - pixel2[2]) < threshold:
        return True
    return False


def find_coordinate(left, img1, img2):
    # 根據判斷結果,返回x坐標
    has_find = False
    for i in range(left, img1.size[0]):  # x坐標
        if has_find:  # 找到不一樣的位置,退出外層循環
            break
        for j in range(img1.size[1]):  # y坐標(從0開始)
            if not compare_pixel(img1, img2, i, j):  # 比較兩張圖片在同一位置的值
                left = i
                has_find = True  # 如果兩張圖片元素不一樣,那么就退出內層循環
                break
    return left

options = ChromeOptions()     #實例化一個ChromeOptions對象,設置參數避免被檢測
options.add_experimental_option('excludeSwitches', ['enable-automation'])  #以鍵值對的形式加入參數
options.add_argument("--no-sandbox")
options.add_argument("--start-maximized")  # 最大化窗口,一定要最大化,不然坐標會不准
options.add_argument('--disable-gpu')
browser=webdriver.Chrome(options=options)
time.sleep(0.6)

browser.get('https://www.bilibili.com/')  # 訪問網站
time.sleep(0.5)

button = browser.find_element_by_xpath('//div[@class="mini-login van-popover__reference"]')  # 登陸
button.click()

browser.switch_to.window(browser.window_handles[1])  # 對於新窗口,切換窗口句柄,不然句柄還保持在上一窗口,后面捕捉會出錯

user = browser.find_element_by_xpath('//input[@id="login-username"]')
user.send_keys('19444338')  # 用戶名
time.sleep(0.5)

passwd = browser.find_element_by_xpath('//input[@id="login-passwd"]')
passwd.send_keys('3346777')  # 密碼
time.sleep(0.5)

login = browser.find_element_by_xpath('//a[@class="btn btn-login"]')  # 點擊登錄,出現驗證碼圖片
login.click()
time.sleep(0.5)


# 滑塊驗證
def slid_verify():
    # 缺口圖片
    img1 = crop_image('缺口圖片.png')
    time.sleep(0.5)

    # 完整圖片
    # JS增刪改查操作元素的屬性
    # #新增屬性
    # driver.execute_script(“arguments[0].%s=arguments[1]” %attributeName,elementObj, value)
    # #修改屬性
    # driver.execute_script(“arguments[0].setAttribute(arguments[1],arguments[2])”, elementObj, attributeName, value)
    # #獲取屬性
    # elementObj.get_attribute(attributeName)
    # #刪除屬性
    # driver.execute_script(“arguments[0].removeAttribute(arguments[1])”,elementObj, attributeName)
    # https://blog.csdn.net/DansonC/article/details/99398096
    img_obj = browser.find_element_by_xpath('//*[@class="geetest_canvas_fullbg geetest_fade geetest_absolute"]')  # 找到圖片,建立對象
    # img_style = img_obj.get_attribute('style')  # 記錄style的值
    browser.execute_script("arguments[0].removeAttribute(arguments[1])",img_obj, 'style')  # 刪除圖片屬性,顯示完整圖片
    img2 = crop_image('完整圖片.png')
    # browser.execute_script("arguments[0].setAttribute(arguments[1],arguments[2])", img_obj, 'style', img_style)  # 將style值添加回去,顯示缺口圖片

    slider = browser.find_element_by_xpath("//div[@class='geetest_slider_button']")  # 找到拖動按鈕
    ActionChains(browser).move_to_element(slider).perform()  # 建立拖動對象
    
    # 獲取滑塊圖片位置
    slid_coor = find_coordinate(2, img1, img2)    
    # 獲取缺口圖片位置
    target_coor = find_coordinate(57, img1, img2)
    print(slid_coor, target_coor)
    target_coor -= 6  # 調整偏移量
    #拖動圖片
    
    track = []  # 用於儲存一次拖動滑塊的距離(不能一次拖到位,不然會被判定為機器)
    i = 0
    # 分為3斷,分別設置不同速度,越接近缺口,越慢
    stagev1 = round((target_coor-slid_coor)/4)  # 第1段(前3/5):分為4次(平均距離移動),stafev1為當前階段的速度
    while i<round(target_coor* 3/5):
        i += stagev1
        track.append(stagev1)
    stagev2 = round((target_coor-i)/7)  # 第2段(3/5到21/25):分為7次(平均距離移動)
    while i<round(target_coor*21/25):
        i += stagev2
        track.append(stagev2)
    stagev3 = 1
    while i<round(target_coor):  # 第3段(21/25到最后):按1為單位移動  
        i += stagev3
        track.append(stagev3)
    ActionChains(browser).click_and_hold(slider).perform()  # 點擊,並按住鼠標不放
    for x in track:
        ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform()  # 拖動,x為一次移動的距離
    time.sleep(0.5)
    ActionChains(browser).release().perform()  # 放開鼠標
    time.sleep(1)
    success_flag = Selector(text=browser.page_source).xpath('/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/div[3]/div/div[2]/text()').extract()[0]
    return success_flag

success_flag = slid_verify()
while '超過' not in success_flag:  # 成功后,會有:'sec 秒的速度超過 score% 的用戶'
    if '怪物吃了拼圖,請重試' == success_flag:  # 這是被判定為機器操作,需要"點擊重試"
        reclick = browser.find_element_by_xpath("//div[@class='geetest_panel_error_content']")
        reclick.click()
    re_verify = browser.find_element_by_xpath("//div[@class='geetest_slider_button']")
    re_verify.click()
    success_flag = slid_verify()
    time.sleep(0.5)

 


免責聲明!

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



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