滑塊驗證碼識別


本文是使用極驗滑動驗證碼的官網做的實驗,沒有賬號的可以先注冊一個賬號 ,地址 :https://account.geetest.com/login
  1. 安裝環境
    1. chromedriver 下載地址 可以根據自己chrome版本和系統自行下載
      地址:http://chromedriver.storage.googleapis.com/index.html
      查看chrome版本 和下載chromedriver頁面:

      將解壓好的文件放入/usr/local/bin目錄中,由於mac的很多目錄都是隱藏的,所以我們按快捷鍵command+shift+g,在彈出的窗口輸入/usr/local/bin,
      就可以打開這個目錄,接着將解壓好的驅動放入此目錄即可。 
      安裝 selenium
    2. pip install selenium
      

        
    3. 安裝 PIL 圖片處理
      當我們輸入pip insall PIL時候會發現錯誤,沒有這個模塊。因為這個模塊安裝是以前版本,在命令行輸入 pip install pillow
      pip install pillow
      

        

    4. 測試
      打開小黑窗
      from selenium import webdriver
      from PIL import Image
      browser = webdriver.Chrome()
      browser.get("http://www.baidu.com")
      

       得到以下結果證明環境沒問題 接下來開始寫代碼咯


 

    寫代碼:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time
from io import BytesIO
from PIL import Image
from selenium.webdriver import ActionChains
from selenium.common.exceptions import TimeoutException
import random

EMAIL = '@qq.com'
PASSWORD = '密碼'


class CrackGeetest():
    """
    初始化
    """

    def __init__(self):
        self.url = 'https://account.geetest.com/login'
        self.browser = webdriver.Chrome()
        self.wait = WebDriverWait(self.browser, 5)
        self.email = EMAIL
        self.password = PASSWORD

    def __del__(self):
        self.browser.close()

    def open(self):
        """
        輸入用戶及密碼
        """
        self.browser.get(self.url)
        email_xpath = '//*[@id="base"]/div[2]/div/div[2]/div[3]/div/form/div[1]/div/div/input'
        email = self.wait.until(EC.presence_of_element_located((By.XPATH, email_xpath)))
        password_xpath = '//*[@id="base"]/div[2]/div/div[2]/div[3]/div/form/div[2]/div/div[1]/input'
        password = self.wait.until(EC.presence_of_element_located((By.XPATH, password_xpath)))
        email.send_keys(self.email)
        password.send_keys(self.password)

    def get_geetest_button(self):
        """

        獲取初始驗證按鈕
        返回按鈕對象
        """
        button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))
        return button

    def get_position(self):
        """

        獲取驗證碼位置-為截取驗證碼准備
        返回驗證碼位置元組
        """
        img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))
        time.sleep(2)
        location = img.location
        size = img.size
        top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[
            'width']
        return (top, bottom, left, right)

    def get_screenshot(self):
        """[summary]

        獲取網頁截圖
        """
        screenshot = self.browser.get_screenshot_as_png()
        screenshot = Image.open(BytesIO(screenshot))
        return screenshot

    def get_geetest_image(self, name='captcha.png'):
        """
        獲取驗證碼圖片
        返回圖片對象
        """
        top, bottom, left, right = self.get_position()
        screenshot = self.get_screenshot()
        # 通過驗證碼圖片的位置從網頁截圖上截取驗證碼
        captcha = screenshot.crop((left, top, right, bottom))
        captcha.save(name)
        return captcha

    def get_slider(self):
        """
        獲取滑塊對象
        """
        slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
        return slider

    def get_track(self, distance):
        """
        根據偏移量獲取移動軌跡

        Arguments:
            distance {[type]} -- 偏移量
        """
        # 移動軌跡
        track = []
        # 當前位移
        current = 0
        # 減速閥值
        mid = distance * 7 / 10
        # 計算間隔
        t = 0.15
        # 初速度
        v = 0

        while current < distance:
            if current < mid:
                # 加速度為正
                a = 2.1
            else:
                # 加速度為負
                a = -4.8
            # 初速度v0
            v0 = v
            # 當前速度 v = v0 + at
            v = v0 + a * t
            # 移動距離 x = v0t + 1/2*a*t*t
            move = v0 * t + 1 / 2 * a * t * t
            # 當前位移
            current += move
            # 加入軌跡
            track.append(round(move, 2))
        return track

    def move_to_gap(self, slider, tracks):
        """[summary]

        拖動滑塊到缺口處
        動作: 點擊且不釋放鼠標-拖拽圖片到缺口-釋放鼠標

        Arguments:
            slider {[type]} -- 滑塊
            tracks {[type]} -- 軌跡
        """
        # 點擊並按住滑塊
        ActionChains(self.browser).click_and_hold(slider).perform()
        # 移動
        for x in tracks:
            ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
        time.sleep(0.1)
        # 釋放滑塊
        ActionChains(self.browser).release().perform()

    def login(self):
        """[summary]

        登錄
        """
        submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-btn')))
        submit.click()
        time.sleep(1)
        print('登錄成功')

    def is_try_again(self):
        """[summary]

        判斷是否能夠點擊重試
        """
        button_text = self.browser.find_element_by_class_name('geetest_radar_tip_content')
        text = button_text.text
        if text == '嘗試過多':
            button = self.browser.find_element_by_class_name('geetest_reset_tip_content')
            button.click()

    def is_success(self):
        """[summary]

        判斷是否成功
        """
        button_text2 = self.browser.find_element_by_class_name('geetest_success_radar_tip_content')
        text2 = button_text2.text
        if text2 == '驗證成功':
            return 1
        return 0

    def for_move(self, x_temp):
        """[summary]

        循環拖動
        """
        flag = 0
        for i in range(0, 7):

            gap = random.randint(16, 20) * i + x_temp
            if gap < 40:
                continue
            print('預估計缺口位置: ', gap)
            self.is_try_again()
            slider = self.get_slider()
            track = self.get_track(gap)
            print('滑動軌跡: ', track)
            # 拖動滑塊
            self.move_to_gap(slider, track)
            time.sleep(3)
            if self.is_success():
                flag = 1
                break
        return flag

    def crack(self):
        """[summary]

        驗證
        """
        try:
            # 輸入用戶和密碼
            self.open()
            time.sleep(2)
            # 點擊驗證按鈕
            button = self.get_geetest_button()
            button.click()
            # 獲取驗證碼圖片
            image1 = self.get_geetest_image('captcha1.png')
            flag = 0
            while 1:
                temp = random.randint(0, 2)  # 將軌跡划分為2, 則有1/2的幾率
                if temp == 0:
                    print('預估左1/2: ')
                    flag = self.for_move(30)
                else:
                    print('預估右1/2: ')
                    flag = self.for_move(120)
                if flag == 1:
                    break

        except TimeoutException as e:
            self.crack()
        # 成功,登錄
        self.login()
        time.sleep(10)


if __name__ == "__main__":
    crack = CrackGeetest()
    crack.crack()

 


免責聲明!

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



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