web 自動化 圖片 滑動驗證碼如何解決


qq空間滑動驗證圖片:

  

本模塊專門用來處理滑動驗證碼的問題

from selenium.webdriver import ActionChains
import random, time, os
import cv2
from PIL import Image as Im
import numpy as np
import requests


class SlideVerificationCode():
    """滑動驗證碼破解"""

    def __init__(self, count=5, save_image=False):
        """
        :param count: 驗證重試的次數,默認為5次
        :param save_image: 是否保存驗證過程中的圖片,默認不保存
        """
        self.count = count
        self.save_image = save_image

    def slide_verification(self, driver, slide_element, distance):
        """
        :param driver: driver對象
        :type driver:webdriver.Chrome
        :param slide_element: 滑塊的元組
        :type slider_ele: WebElement
        :param distance:  滑動的距離
        :type: int
        :return:
        """
        start_url = driver.current_url
        print("需要滑動的距離為:", distance)
        locus = self.get_slide_locus(distance)
        print("生成的滑動軌跡為:{},軌跡的距離之和為{}".format(locus, distance))
        ActionChains(driver).click_and_hold(slide_element).perform()
        time.sleep(0.5)
        for loc in locus:
            time.sleep(0.01)
            ActionChains(driver).move_by_offset(loc, random.randint(-5, 5)).perform()
            ActionChains(driver).context_click(slide_element)
        ActionChains(driver).release(on_element=slide_element).perform()
        time.sleep(2)
        end_url = driver.current_url
        if start_url == end_url and self.count > 0:
            print("第{}次驗證失敗,開啟重試".format(6 - self.count))
            self.count -= 1
            self.slide_verification(driver, slide_element, distance)

    def onload_save_img(self, url, filename="image.png"):
        """
        下載圖片保存
        :param url:圖片地址
        :param filename: 保存的圖片名
        :return:
        """
        try:
            response = requests.get(url=url)
        except(requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError)as e:
            print("圖片下載失敗")
            raise e
        else:
            with open(filename, "wb") as f:
                f.write(response.content)

    def get_element_slide_distance(self, slider_ele, background_ele, correct=0):
        """
        根據傳入滑塊,和背景的節點,計算滑塊的距離

        該方法只能計算 滑塊和背景圖都是一張完整圖片的場景,
        如果是通過多張小圖拼接起來的背景圖,該方法不適用,后續會補充一個專門針對處理該場景的方法
        :param slider_ele: 滑塊圖片的節點
        :type slider_ele: WebElement
        :param background_ele: 背景圖的節點
        :type background_ele:WebElement
        :param correct:滑塊缺口截圖的修正值,默認為0,調試截圖是否正確的情況下才會用
        :type: int
        :return: 背景圖缺口位置的X軸坐標位置(缺口圖片左邊界位置)
        """
        slider_url = slider_ele.get_attribute("src")
        background_url = background_ele.get_attribute("src")
        slider = "slider.jpg"
        background = "background.jpg"
        self.onload_save_img(slider_url, slider)
        self.onload_save_img(background_url, background)
        slider_pic = cv2.imread(slider, 0)
        background_pic = cv2.imread(background, 0)
        width, height = slider_pic.shape[::-1]
        slider01 = "slider01.jpg"
        background_01 = "background01.jpg"
        cv2.imwrite(background_01, background_pic)
        cv2.imwrite(slider01, slider_pic)
        slider_pic = cv2.imread(slider01)
        slider_pic = cv2.cvtColor(slider_pic, cv2.COLOR_BGR2GRAY)
        slider_pic = abs(255 - slider_pic)
        cv2.imwrite(slider01, slider_pic)
        slider_pic = cv2.imread(slider01)
        background_pic = cv2.imread(background_01)
        result = cv2.matchTemplate(slider_pic, background_pic, cv2.TM_CCOEFF_NORMED)
        top, left = np.unravel_index(result.argmax(), result.shape)
        print("當前滑塊的缺口位置:", (left, top, left + width, top + height))
        if self.save_image:
            loc = (left + correct, top + correct, left + width - correct, top + height - correct)
            self.image_crop(background, loc)
        else:
            os.remove(slider01)
            os.remove(background_01)
            os.remove(slider)
            os.remove(background)
        return left

    def get_image_slide_dictance(self, slider_image, background_image, correct=0):
        """
        根據傳入滑塊,和背景的圖片,計算滑塊的距離

        該方法只能計算 滑塊和背景圖都是一張完整圖片的場景,
        如果是通過多張小圖拼接起來的背景圖,該方法不適用,后續會補充一個專門針對處理該場景的方法
        :param slider_iamge: 滑塊圖的圖片
        :type slider_image: str
        :param background_image: 背景圖的圖片
        :type background_image: str
        :param correct:滑塊缺口截圖的修正值,默認為0,調試截圖是否正確的情況下才會用
        :type: int
        :return: 背景圖缺口位置的X軸坐標位置(缺口圖片左邊界位置)
        """
        slider_pic = cv2.imread(slider_image, 0)
        background_pic = cv2.imread(background_image, 0)
        width, height = slider_pic.shape[::-1]
        slider01 = "slider01.jpg"
        background_01 = "background01.jpg"
        cv2.imwrite(background_01, background_pic)
        cv2.imwrite(slider01, slider_pic)
        slider_pic = cv2.imread(slider01)
        slider_pic = cv2.cvtColor(slider_pic, cv2.COLOR_BGR2GRAY)
        slider_pic = abs(255 - slider_pic)
        cv2.imwrite(slider01, slider_pic)
        slider_pic = cv2.imread(slider01)
        background_pic = cv2.imread(background_01)
        result = cv2.matchTemplate(slider_pic, background_pic, cv2.TM_CCOEFF_NORMED)
        top, left = np.unravel_index(result.argmax(), result.shape)
        print("當前滑塊的缺口位置:", (left, top, left + width, top + height))
        if self.save_image:
            loc = (left + correct, top + correct, left + width - correct, top + height - correct)
            self.image_crop(background_image, loc)
        else:
            os.remove(slider01)
            os.remove(background_01)
        return left

    @classmethod
    def get_slide_locus(self, distance):
        """
        根據移動坐標位置構造移動軌跡,前期移動慢,中期塊,后期慢
        :param distance:移動距離
        :type:int
        :return:移動軌跡
        :rtype:list
        """
        remaining_dist = distance
        locus = []
        while remaining_dist > 0:
            ratio = remaining_dist / distance
            if ratio < 0.2:
                span = random.randint(2, 8)
            elif ratio > 0.8:
                span = random.randint(5, 8)
            else:
                span = random.randint(10, 16)
            locus.append(span)
            remaining_dist -= span
        return locus

    def image_crop(self, image, location, new_name="new_image.png"):
        """
        對圖片的指定位置進行截圖
        :param image: 被截取圖片的坐標位置
        :param location:需要截圖的坐標位置:(left,top,right,button)
        :type location: tuple
        :return:
        """
        image = Im.open(image)
        imagecrop = image.crop(location)
        imagecrop.save(new_name)

qq空間登錄滑動圖片驗證

import time
from selenium import webdriver
from web_項目前期.AlideVerification.slideVerfication import SlideVerificationCode

# 1、創建一個driver對象,訪問qq登錄頁面
browser = webdriver.Chrome()
browser.get("https://qzone.qq.com/")

# 2、輸入賬號密碼

# 2.0 點擊切換到登錄的iframe
browser.switch_to.frame('login_frame')

# 2.1 點擊賬號密碼登錄
browser.find_element_by_id('switcher_plogin').click()

# 2.2定位賬號輸入框,輸入賬號
browser.find_element_by_id("u").send_keys("1938091409")

# 2.3定位密碼輸入輸入密碼
browser.find_element_by_id("p").send_keys("aini2141339856.0")

# 3、點擊登錄
browser.find_element_by_id('login_button').click()
time.sleep(3)

# 4、模擬滑動驗證
# 4.1切換到滑動驗證碼的iframe中
tcaptcha = browser.find_element_by_id("tcaptcha_iframe")
browser.switch_to.frame(tcaptcha)

# 4.2選擇拖動滑塊的節點
slide_element = browser.find_element_by_id('tcaptcha_drag_thumb')

#  模擬拖到滑塊進行識別
sc = SlideVerificationCode(save_image=True)

# 獲取滑塊圖片的節點id="slideBlock"
slideBlock_ele = browser.find_element_by_id('slideBlock')
# 獲取背景圖片節點id="slideBg"
slideBg = browser.find_element_by_id('slideBg')

# 4.3計算滑動距離,電腦縮放比例需要為100% 才可確保減去的正確
distance = sc.get_element_slide_distance(slideBlock_ele, slideBg)
print("滑動的距離為:", distance)
# 滑動距離誤差校正,按照比例來進行計算,然后減去 第一部分距離
distance = distance*(280 / 680) - 31

print("校驗后的滑動距離", distance)

# 4.4、進行滑動
sc.slide_verification(browser, slide_element, distance=distance)

time.sleep(2)
browser.close()

 

 

*******請大家尊重原創,如要轉載,請注明出處:轉載自:https://www.cnblogs.com/shouhu/,謝謝!!******* 


免責聲明!

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



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