pyppeteer 滑块验证

#!/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())

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值