python 实现京东滑块验证码登录

话不多说直接上代码, 不懂的直接看注释或者私信

import time

from urllib import request

import cv2
import pyautogui
from selenium import webdriver
from selenium.webdriver import ChromeOptions
import random

# 登陆账号
USERNAME = 'xxxx'
# 登陆密码
PASSWORD = 'xxxx'
# 滑块距离屏幕左上角的x, y像素, 需根据自己屏幕大小调整
SLIDE_X_POSITION, SLIDE_Y_POSITION = 881, 441


class SlideUtils:

    @staticmethod
    def find_pic(background, slide):
        """
        获取背景图与滑块图的最佳位置
        """
        # 读取背景灰度图片
        background_gray = cv2.imread(background, 0)
        # 读取滑块灰度图片
        slide_gray = cv2.imread(slide, 0)
        # 匹配滑块位置
        res = cv2.matchTemplate(background_gray, slide_gray, cv2.TM_CCOEFF_NORMED)
        # 获取最佳与最差匹配
        value = cv2.minMaxLoc(res)
        return value[2][0]

    @staticmethod
    def slide_by_autogui(x, y, offset):
        """
        使用pyautogui实现滑块并自定义轨迹方程
        """
        xx = x + offset
        pyautogui.moveTo(x, y, duration=0.1)
        pyautogui.mouseDown()
        y += random.randint(9, 19)
        pyautogui.moveTo(x + int(offset * random.randint(15, 23) / 20), y, duration=0.28)
        y += random.randint(-9, 0)
        pyautogui.moveTo(x + int(offset * random.randint(17, 21) / 20), y, duration=random.randint(20, 31) / 100)
        y += random.randint(0, 8)
        pyautogui.moveTo(xx, y, duration=0.3)
        pyautogui.mouseUp()


def send_keys_interval(element, text, interval=0.1):
    """
    webdriver 模拟人输入文本信息
    """
    for c in text:
        element.send_keys(c)
        time.sleep(random.randint(int(interval * 500), int(interval * 1500)) / 1000)


class JdLoginChromeWebdriverPlus:
    """
    京东登录chrome webdriver增强
    """
    def __init__(self, retry_times=5):
        option = ChromeOptions()
        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        self.driver = webdriver.Chrome(options=option)
        self.driver.maximize_window()
        self.retry_times = retry_times
        self.login_success = False

    def login(self, username, password):
        driver = self.driver
        driver.get('https://passport.jd.com/uc/login')
        # 切換账号密码登录
        driver.find_element_by_class_name('login-tab-r').find_element_by_tag_name('a').click()
        # 设置账号密码
        send_keys_interval(driver.find_element_by_id('loginname'), username)
        send_keys_interval(driver.find_element_by_id('nloginpwd'), password)

        time.sleep(random.random())

        # 登录
        driver.find_element_by_id('loginsubmit').click()

        time.sleep(random.randint(1, 3))

        for i in range(self.retry_times):
            # 获取验证码图片
            # 用于找到登录图片的大图
            try:
                background = driver.find_element_by_xpath(r'//div/div[@class="JDJRV-bigimg"]/img')
            except:
                # 未查找到登陆图片则认为成功
                self.login_success = True
                break
            # 用来找到登录图片的小滑块
            slide = driver.find_element_by_xpath(r'//div/div[@class="JDJRV-smallimg"]/img')
            background_url = background.get_attribute("src")
            slide_url = slide.get_attribute("src")
            background_img = 'background_img.png'
            slide_img = 'slide_img.png'
            # 下载背景大图保存到本地
            request.urlretrieve(background_url, background_img)
            # 下载滑块保存到本地
            request.urlretrieve(slide_url, slide_img)
            # 获取最佳x偏移量
            x = SlideUtils.find_pic(background_img, slide_img)
            print(f'本地最佳偏移量: {
      
      x}')
            # 计算缩放
            # 获取下载背景图宽度
            w1 = cv2.imread(background_img).shape[1]
            # 获取网页背景图宽度
            w2 = background.size['width']
            # 计算实际页面x偏移量
            x = x * w2 / w1
            print(f'实际最佳偏移量: {
      
      x}')
            # 其中x为屏幕左上角至滑块中心的横向像素值,y为屏幕左上角至滑块中心纵向像素值, 可根据自己屏幕配置
            SlideUtils.slide_by_autogui(SLIDE_X_POSITION, SLIDE_Y_POSITION, x)

    def is_login(self):
        """
        是否已登录成功 
        """
        return self.login_success

    def get_cookies(self):
        """
        获取webdriver cookies
        """
        return self.driver.get_cookies()

    def get_cookies_dict(self):
        """
        获取字典结构的cookie
        """
        cookies = self.get_cookies()
        res = {
    
    }
        for cookie in cookies:
            res[cookie['name']] = cookie['value']
        return res

    def get_driver(self):
        """
        获取webdriver对象
        """
        return self.driver

    def close(self):
        self.driver.close()

    def quit(self):
        self.driver.quit()


driver = JdLoginChromeWebdriverPlus()
driver.login(USERNAME, PASSWORD)
print(driver.is_login())
print(driver.get_cookies_dict())
driver.quit()

滑块轨迹方程参考: https://www.bilibili.com/video/BV1cC4y1Y7Wm

猜你喜欢

转载自blog.csdn.net/qq_33129963/article/details/122978406