selenium破解網(wǎng)易易盾滑塊

前言

之前由于工作原因做過極驗驗證的滑塊驗證碼,該網(wǎng)站的滑塊驗證碼是直接能提取出全圖片和缺口圖片,利用pillow模塊的ImageChops.difference差值算法解決起來比較簡單;后來發(fā)現(xiàn)了網(wǎng)易易盾這種滑塊驗證碼,他只能提取兩個圖片的鏈接(缺口圖片和待滑動的小圖片)。本文就是網(wǎng)易易盾滑塊的破解。

獲取滑塊驗證碼的圖片

def get_img(self, target, template, xp):  # 參數(shù)分別為兩個待保存的圖片名,和缺口圖片的像素(長)
    target_link = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'yidun_bg-img'))).get_attribute('src')  # 獲取缺口圖片鏈接
    template_link = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'yidun_jigsaw'))).get_attribute('src')  # 獲取待滑動圖片鏈接
    target_img = Image.open(BytesIO(requests.get(target_link).content))  # 從網(wǎng)頁端讀取圖片
    template_img = Image.open(BytesIO(requests.get(template_link).content))
    target_img.save(target)  # 保存圖片
    template_img.save(template)
    size_loc = target_img.size  # 獲取圖片大小
    zoom = xp / int(size_loc[0])  # 耦合像素
    return zoom

去除待滑動的圖片的黑邊

def change_size(self, file):
    image = cv2.imread(file, 1)  # 讀取圖片 image_name應(yīng)該是變量
    img = cv2.medianBlur(image, 5)  # 中值濾波,去除黑色邊際中可能含有的噪聲干擾
    b = cv2.threshold(img, 15, 255, cv2.THRESH_BINARY)  # 調(diào)整裁剪效果
    binary_image = b[1]  # 二值圖--具有三通道
    binary_image = cv2.cvtColor(binary_image, cv2.COLOR_BGR2GRAY)
    x, y = binary_image.shape
    edges_x = []
    edges_y = []
    for i in range(x):
        for j in range(y):
            if binary_image[i][j] == 255:
                edges_x.append(i)
                edges_y.append(j)
    left = min(edges_x)  # 左邊界
    right = max(edges_x)  # 右邊界
    width = right - left  # 寬度
    bottom = min(edges_y)  # 底部
    top = max(edges_y)  # 頂部
    height = top - bottom  # 高度
    pre1_picture = image[left:left + width, bottom:bottom + height]  # 圖片截取
    return pre1_picture  # 返回圖片數(shù)據(jù)

算出缺口的位置

def match(self, target, template):
    img_gray = cv2.imread(target, 0)
    img_rgb = self.change_size(template)
    template = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
    res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
    run = 1
    # 使用二分法查找閾值的精確值
    L = 0
    R = 1
    while run < 20:
        run += 1
        threshold = (R + L) / 2
        if threshold < 0:
            print('Error')
            return None
        loc = np.where(res >= threshold)
        if len(loc[1]) > 1:
            L += (R - L) / 2
        elif len(loc[1]) == 1:
            break
        elif len(loc[1]) < 1:
            R -= (R - L) / 2
    return loc[1][0]

模擬變加速

def get_tracks(self, distance, seconds, ease_func):
    distance += 20
    tracks = [0]
    offsets = [0]
    for t in np.arange(0.0, seconds, 0.1):
        ease = ease_func
        offset = round(ease(t / seconds) * distance)
        tracks.append(offset - offsets[-1])
        offsets.append(offset)
    tracks.extend([-3, -2, -3, -2, -2, -2, -2, -1, -0, -1, -1, -1])
    return tracks

def ease_out_quart(self, x):
    return 1 - pow(1 - x, 4)

完整代碼

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Descr : 
# @Atten : 
# @Author: luqin
# @File  : wyyd.py
# @Vers  : 1.0
# @Time  : 2020-07-23 18:13
import os
import cv2
import time
import random
import requests
import numpy as np
from PIL import Image
from io import BytesIO
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from common.selenium_spider import SeleniumSpider
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class CrackSlider():
    def __init__(self):
        desired_capabilities = webdriver.DesiredCapabilities.CHROME.copy()
        desired_capabilities['chromeOptions'] = {
            'args': [
                '--window-size=1400,850',
                # '--proxy-server=http://127.0.0.1:8888'  # 加代理方便抓包
            ],
            'extensions': []
        }
        self.path = os.path.join(os.path.dirname(__file__), "common/chromedriver")
        self.driver = SeleniumSpider(
            desired_capabilities=desired_capabilities,
            path='/usr/local/bin/chromedriver')  # driver的路徑
        self.url = 'http://dun.163.com/trial/jigsaw'  # 測試網(wǎng)站
        self.wait = WebDriverWait(self.driver, 20)
        self.driver.get(self.url)

    def get_img(self, target, template, xp):
        target_link = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'yidun_bg-img'))).get_attribute('src')
        template_link = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'yidun_jigsaw'))).get_attribute('src')
        target_img = Image.open(BytesIO(requests.get(target_link).content))
        template_img = Image.open(BytesIO(requests.get(template_link).content))
        target_img.save(target)
        template_img.save(template)
        size_loc = target_img.size
        zoom = xp / int(size_loc[0])  # 耦合像素
        return zoom

    def change_size(self, file):
        image = cv2.imread(file, 1)  # 讀取圖片 image_name應(yīng)該是變量
        img = cv2.medianBlur(image, 5)  # 中值濾波,去除黑色邊際中可能含有的噪聲干擾
        b = cv2.threshold(img, 15, 255, cv2.THRESH_BINARY)  # 調(diào)整裁剪效果
        binary_image = b[1]  # 二值圖--具有三通道
        binary_image = cv2.cvtColor(binary_image, cv2.COLOR_BGR2GRAY)
        x, y = binary_image.shape
        edges_x = []
        edges_y = []
        for i in range(x):
            for j in range(y):
                if binary_image[i][j] == 255:
                    edges_x.append(i)
                    edges_y.append(j)

        left = min(edges_x)  # 左邊界
        right = max(edges_x)  # 右邊界
        width = right - left  # 寬度
        bottom = min(edges_y)  # 底部
        top = max(edges_y)  # 頂部
        height = top - bottom  # 高度
        pre1_picture = image[left:left + width, bottom:bottom + height]  # 圖片截取
        return pre1_picture  # 返回圖片數(shù)據(jù)

    def match(self, target, template):
        img_gray = cv2.imread(target, 0)
        img_rgb = self.change_size(template)
        template = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
        # cv2.imshow('template', template)
        # cv2.waitKey(0)
        res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
        run = 1

        # 使用二分法查找閾值的精確值
        L = 0
        R = 1
        while run < 20:
            run += 1
            threshold = (R + L) / 2
            if threshold < 0:
                print('Error')
                return None
            loc = np.where(res >= threshold)
            if len(loc[1]) > 1:
                L += (R - L) / 2
            elif len(loc[1]) == 1:
                break
            elif len(loc[1]) < 1:
                R -= (R - L) / 2
        return loc[1][0]

    def move_to_gap(self, tracks):
        slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider')))
        ActionChains(self.driver).click_and_hold(slider).perform()
        while tracks:
            x = tracks.pop(0)
            ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
            time.sleep(0.05)
        time.sleep(0.05)
        ActionChains(self.driver).release().perform()

    def get_tracks(self, distance, seconds, ease_func):
        distance += 20
        tracks = [0]
        offsets = [0]
        for t in np.arange(0.0, seconds, 0.1):
            ease = ease_func
            offset = round(ease(t / seconds) * distance)
            tracks.append(offset - offsets[-1])
            offsets.append(offset)
        tracks.extend([-3, -2, -3, -2, -2, -2, -2, -1, -0, -1, -1, -1])
        return tracks

    def ease_out_quart(self, x):
        return 1 - pow(1 - x, 4)


if __name__ == '__main__':
    xp = 320  # 驗證碼的像素-長
    target = 'target.jpg'  # 臨時保存的圖片名
    template = 'template.png'  # 臨時保存的圖片名

    cs = CrackSlider()
    zoom = cs.get_img(target, template, xp)
    distance = cs.match(target, template)
    track = cs.get_tracks((distance + 7) * zoom, random.randint(2, 4), cs.ease_out_quart)
    cs.move_to_gap(track)
    time.sleep(2)
    cs.driver.close()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容