#!/usr/bin/python3.9
# -*- coding: UTF-8 -*-
import base64
import random
import time
import httpx
from pyppeteer import launch
import asyncio
import cv2
class CrackSlider(object):
def __init__(self, username, password, login_url):
self.chrome_extension = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
self.launch_kwargs = {
# 控制是否为无头模式
'executablePath': self.chrome_extension, # chrome 文件目录位置
"headless": False,
"dumpio": True,
# 当界面开多了时会卡住,设置这个参数就不会了
# "userDataDir": r"./ceshi1",
'autoClose': True,
# chrome启动命令行参数
"args": ["--start-maximized", "--no-sandbox", "--disable-infobars"],
"ignoreDefaultArgs": ['--enable-automation'] # 去除Chrome正受到自动测试软件的控制
}
self.username = username
self.password = password
self.login_url = login_url
self.target = "./target.png"
self.template = "./template.png"
async def start_parse(self):
self.browser = await launch(self.launch_kwargs)
page = await self.browser.newPage()
await page.setViewport({"width": 1920, "height": 1080})
await page.evaluateOnNewDocument(
'() =>{ Object.defineProperties(navigator,''{ webdriver:{ get: () => false } }) }')
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36')
await page.goto(self.login_url, waitUntil='networkidle0') # 等待网页加载完成
await page.type('#account_pop', self.username)
await page.type('#actpwd_pop', self.password)
await (await page.xpath("//a[@id='commonLoginBtn']"))[0].click()
await page.waitFor(1000)
template_img_tag = await page.xpath("//div[@class='shumei_captcha_img_loaded_fg_wrapper']//img")
template_img_data = await (await template_img_tag[0].getProperty("src")).jsonValue()
await self.get_decode_image(self.template, template_img_data)
target_img_tag = await page.xpath("//div[@class='shumei_captcha_img_loaded_bg_wrapper']//img")
target_img_data = await (await target_img_tag[0].getProperty("src")).jsonValue()
await self.get_decode_image(self.target, target_img_data)
total_length, min_length = await self.match_picture_position()
await self.simulated_sliding(page, min_length, total_length)
async def simulated_sliding(self, page, min_length, total_length):
"""
:param page: page对象
:return:
"""
# el = await page.querySelector('#dx_captcha_basic_slider-img-hover_1')
# box = await el.boundingBox()
await page.hover('.shumei_captcha_slide_btn') # 鼠标移动方块上
await page.mouse.down() # 鼠标拖动操作包括按下、移动、放开
await page.waitFor(1000)
# await page.mouse.move(page.mouse._x + total_length, page.mouse._y,
# {'delay': random.randint(1000, 2000), 'steps': 30})
# await page.waitFor(1000)
# page.mouse._x 当前鼠标的位置
length_list = self.slide_list(total_length)
for length in length_list:
await page.mouse.move(page.mouse._x + length, page.mouse._y,
{'delay': random.randint(1000, 2000), 'steps': 3})
await page.mouse.move(page.mouse._x - 1, page.mouse._y,
{'delay': random.randint(1000, 2000), 'steps': 3})
await page.waitFor(1000)
await page.mouse.up()
await page.waitFor(1000)
await page.close() # 关闭页面
await self.browser.close()
async def match_picture_position(self):
"""
找出图像中最佳匹配位置
:param target: 目标即背景图
:param template: 模板即需要找到的图
:return: 返回最佳匹配及其最差匹配和对应的坐标x的值
"""
size_1 = 0.5 # 图片缩放比例
size_2 = 0.5
target_rgb = cv2.imread(self.target, 0)
target_rgb1 = cv2.resize(target_rgb, (0, 0), fx=size_1, fy=size_1, interpolation=cv2.INTER_NEAREST)
template_rgb = cv2.imread(self.template, 0)
template_rgb1 = cv2.resize(template_rgb, (0, 0), fx=size_2, fy=size_2, interpolation=cv2.INTER_NEAREST)
res = cv2.matchTemplate(target_rgb1, template_rgb1, cv2.TM_CCOEFF_NORMED)
value = cv2.minMaxLoc(res)
print(value)
return value[3][0], value[2][0]
async def get_decode_image(self, filename, data):
if "base64" in data:
_, img = data.split(",")
img = base64.b64decode(img)
else:
img = httpx.get(data).content
with open(filename, "wb") as f:
f.write(img)
def slide_list(self, total_length):
'''
拿到移动轨迹,模仿人的滑动行为,先匀加速后匀减速
匀变速运动基本公式:
①v=v0+at
②s=v0t+½at²
③v²-v0²=2as
:param total_length: 需要移动的距离
:return: 每段移动的距离列表
'''
v = 0 # 初速度
t = 1 # 单位时间为0.3s来统计轨迹,轨迹即0.3内的位移
slide_result = [] # 位移/轨迹列表,列表内的一个元素代表一个T时间单位的位移,t越大,每次移动的距离越大
current = 0 # 当前的位移
mid = total_length * 3 / 5 # 到达mid值开始减速
while current < total_length:
if current < mid:
a = 0.4 # 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
else:
a = -0.5
v0 = v # 初速度
s = v0 * t + 0.5 * a * (t ** 2) # 0.2秒时间内的位移
current += s # 当前的位置
slide_result.append(round(s)) # 添加到轨迹列表
v = v0 + a * t # 速度已经达到v,该速度作为下次的初速度
return slide_result
if __name__ == '__main__':
user = '18253535353'
passwd = 'hjfhakjshkjds12'
url = 'aHR0cHM6Ly9wYXNzcG9ydC5seS5jb20vP3BhZ2V1cmw9aHR0cHMlM0ElMkYlMkZ3d3cubHkuY29tJTJGZmxpZ2h0cyUyRmhvbWUjIHN0YXJ0ID0gdGltZS50aW1lKCk=' # 脱敏处理
cs = CrackSlider(user, passwd, url)
loop = asyncio.get_event_loop()
loop.run_until_complete(cs.start_parse())
pyppeteer 滑块验证
于 2022-03-04 16:22:37 首次发布