话不多说直接上代码, 不懂的直接看注释或者私信
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