吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2799|回复: 28
收起左侧

[求助] yidun滑块验证,python如何做到模拟手工拖动滑块一样丝滑?

[复制链接]
Pojie1999.0909 发表于 2021-11-12 13:27
200吾爱币

yidun滑块地址:[http://app.miit-eidc.org.cn/miitxxgk/gonggao/xxgk/queryCpParamPage?dataTag=Z&gid=U3119671&pc=303]http://app.miit-eidc.org.cn/miitxxgk/gonggao/xxgk/queryCpParamPage?dataTag=Z&gid=U3119671&pc=303](http://app.miit-eidc.org.cn/miitxxgk/gonggao/xxgk/queryCpParamPage?dataTag=Z&gid=U3119671&pc=303]http://app.miit-eidc.org.cn/miitxxgk/gonggao/xxgk/queryCpParamPage?dataTag=Z&gid=U3119671&pc=303)

我已找到一份python代码,可以准确识别出滑块的位置,效果如下(不能传gif,放阿里云盘了):
我用阿里云盘分享了「Animation1.gif」,你可以不限速下载🚀复制这段内容打开「阿里云盘」App 即可获取链接:https://www.aliyundrive.com/s/NUe6jj686Z8

上面阿里云盘分享的gif图片中,可以将滑块准确拖动到对应的位置,但是依然不能通过验证。有没有大佬可以指点一下?

代码如下:

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 selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class CrackSlider():
    def __init__(self):
    self.browser = webdriver.Edge()
    self.s2 = r'//*[@id="captcha_div"]/div/div[1]/div/div[1]/img[1]'
    self.s3 = r'//*[@id="captcha_div"]/div/div[1]/div/div[1]/img[2]'
    self.url = 'http://app.miit-eidc.org.cn/miitxxgk/gonggao/xxgk/queryCpParamPage?dataTag=Z&gid=U3119671&pc=303'  # 测试网站
    self.wait = WebDriverWait(self.browser, 20)
    self.browser.get(self.url)

    def get_img(self, target, template, xp):
        time.sleep(3)
        target_link = self.browser.find_element_by_xpath(self.s2).get_attribute("src")
        template_link = self.browser.find_element_by_xpath(self.s3).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
        print('size_loc[0]-----\n')
        print(size_loc[0])
        zoom = xp / int(size_loc[0])  # 耦合像素
        print('zoom-----\n')
        print(zoom)
        return zoom

    def change_size(self, file):
        image = cv2.imread(file, 1)  # 读取图片 image_name应该是变量
        img = cv2.medianBlur(image, 5)  # 中值滤波,去除黑色边际中可能含有的噪声干扰
        b = cv2.threshold(img, 15, 255, cv2.THRESH_BINARY)  # 调整裁剪效果
        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  # 返回图片数据

    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
        res = loc[1][0]
        print('match distance-----\n')
        print(res)
        return res

    def move_to_gap(self, tracks):
        slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider')))
        ActionChains(self.browser).click_and_hold(slider).perform()
        #element = self.browser.find_element_by_xpath(self.s3)
        #ActionChains(self.browser).click_and_hold(on_element=element).perform()
        while tracks:
            x = tracks.pop(0)
            print('tracks.pop(0)-----\n')
            print(x)
            ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
            #ActionChains(self.browser).move_to_element_with_offset(to_element=element, xoffset=x, yoffset=0).perform()
            #time.sleep(0.01)
        time.sleep(0.05)
        ActionChains(self.browser).release().perform()

    def move_to_gap1(self, distance):
        distance += 46
        time.sleep(1)
        element = self.browser.find_element_by_xpath(self.s3)
        ActionChains(self.browser).click_and_hold(on_element=element).perform()
        ActionChains(self.browser).move_to_element_with_offset(to_element=element, xoffset=distance, yoffset=0).perform()
        #ActionChains(self.browser).release().perform()
        time.sleep(1.38)
        ActionChains(self.browser).release(on_element=element).perform()

    def move_to_gap2(self, distance):
        element = self.browser.find_elements_by_class_name("yidun_slider")[0]
        action = ActionChains(self.browser)
        mouse_action = action.click_and_hold(on_element=element)
        distance += 11
        distance = int(distance * 32/33)
        move_steps = int(distance/4)
        for i in range(0,move_steps):
            mouse_action.move_by_offset(4,random.randint(-5,5)).perform()
        time.sleep(0.1)
        mouse_action.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
            print('ease-----\n')
            print(ease)
            offset = round(ease(t / seconds) * distance)
            print('offset-----\n')
            print(offset)
            tracks.append(offset - offsets[-1])
            print('offset - offsets[-1]-----\n')
            print(offset - offsets[-1])
            offsets.append(offset)
            print('offsets-----\n')
            print(offsets)
        tracks.extend([-3, -2, -3, -2, -2, -2, -2, -1, -0, -1, -1, -1])
        return tracks
    def get_tracks1(self,distance):
        """
        根据偏移量获取移动轨迹
        :param distance: 偏移量
        :return: 移动轨迹
        """
        # 移动轨迹
        track = []
        # 当前位移
        current = 0
        # 减速阈值
        mid = distance * 4 / 5
        # 计算间隔
        t = 0.2
        # 初速度
        v = 0

        while current < distance:
            if current < mid:
                # 加速度为正 2
                a = 4
            else:
                # 加速度为负 3
                a = -3
            # 初速度 v0
            v0 = v
            # 当前速度 v = v0 + at
            v = v0 + a * t
            # 移动距离 x = v0t + 1/2 * a * t^2
            move = v0 * t + 1 / 2 * a * t * t
            # 当前位移
            current += move
            # 加入轨迹
            track.append(round(move))
        return track

    def ease_out_quart(self, x):
        res = 1 - pow(1 - x, 4)
        print('ease_out_quart-----\n')
        print(res)
        return res

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)
    #track = cs.get_tracks1(distance)
    #track = cs.get_tracks((distance + 7) * zoom, random.randint(1, 2), cs.ease_out_quart)
    cs.move_to_gap(track)
    #cs.move_to_gap1(distance)
    #cs.move_to_gap2(distance)
    time.sleep(2)
    #cs.browser.close()
image.png

最佳答案

查看完整内容

from pyppeteer import launch import asyncio import time import json import random import cv2 def get_track(length): list = [] x = random.randint(1,10) while length: list.append(x) length -= x if length > 0 and length = threshold) if len(loc[1]) > 1: L += (R - L) / 2 elif len(loc[1]) ...

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Prozacs 发表于 2021-11-12 13:27
本帖最后由 Prozacs 于 2021-11-12 14:27 编辑

from pyppeteer import launch
import asyncio
import time
import json
import random
import cv2

def get_track(length):
    list = []
    x = random.randint(1,10)
    while length:
        list.append(x)
        length -= x
        if length > 0 and length <= 5:
            break
        elif 5 < length < 25:
            x = random.randint(2,length)
        else:
            x = random.randint(5,25)
    for i in range(length):
        list.append(1)
    return list

def change_size( file):
    image = cv2.imread(file, 1)  # 读取图片 image_name应该是变量
    img = cv2.medianBlur(image, 5)  # 中值滤波,去除黑色边际中可能含有的噪声干扰
    b = cv2.threshold(img, 15, 255, cv2.THRESH_BINARY)  # 调整裁剪效果
    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[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  # 返回图片数据
async def main(url):
    try:
        browser = await launch({'headless':False, 'dumpio': True, 'autoClose': False, 'args': ['--no-sandbox', '--window-size=1366,850']})
        page = await browser.newPage()
        await page.evaluateOnNewDocument('''() => {delete navigator.__proto__.webdriver;}''')
        await page.evaluateOnNewDocument('''() => {Object.defineProperty(navigator, 'webdriver', {get: () => undefined,});}''')
        await page.evaluateOnNewDocument('''() =>{ Object.defineProperty(navigator, 'languages', { get: () => ['en-CN', 'cn'] }); }''')
        await page.evaluateOnNewDocument('''() =>{ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5, 6], }); }''')
        await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36')
        await page.setViewport({'width': 1366, 'height': 850})  # 更改浏览器分辨率
        await page.goto(url, {'waitUntil': 'domcontentloaded'})  # 进行第一次访问
        await page.waitFor(3000)
        authUrl = await page.content()
        if authUrl.find('向右拖动滑块填充拼图') != -1:
            el = await page.querySelector('#captcha_div > div > div.yidun_control')
            box = await el.boundingBox()
            while True:
                imageCard_list = []
                for imgItem in await page.xpath('//*[@id="captcha_div"]/div/div[1]/div/div[1]/img'):
                    imageCard = await (await imgItem.getProperty('src')).jsonValue()
                    imageCard_list.append(imageCard)
                from PIL import Image
                from io import BytesIO
                import requests
                import numpy as np
                target = 'target.jpg'  # 临时保存的图片名
                template = 'template.png'
                target_img = Image.open(BytesIO(requests.get(imageCard_list[0]).content))
                template_img = Image.open(BytesIO(requests.get(imageCard_list[1]).content))
                target_img.save(target)
                template_img.save(template)
                img_gray = cv2.imread(target, 0)
                img_rgb = 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
                res = loc[1][0]
                await page.hover('#captcha_div > div > div.yidun_control > div.yidun_slider')  # 鼠标移动方块上
                await page.mouse.down({'delay': random.randint(20, 100), 'steps': 30})  # 鼠标拖动操作包括按下、移动、放开
                sixx = get_track(int(res+25))
                print(sixx)
                s = 0
                for i in sixx:
                    s += i
                    if i % 2:
                        await page.mouse.move(box['x'] + s, box['y'], {'delay': random.randint(20, 45), 'steps': 5})
                    else:
                        await page.mouse.move(box['x'] + s, random.randint(int(box['y']) + 10, int(box['y']) + 20), {'delay': random.randint(20, 45), 'steps': 5})
                await page.waitFor(random.randint(50, 150))
                await page.mouse.up({'delay': random.randint(20, 100), 'steps': 20})
                await page.waitFor(1000)
                authUrl = await page.content()
                if '向右拖动滑块填充拼图' in authUrl:
                    continue
                else:
                    user_ck = await page.xpath(f'//*[@id="submit-btn"]')
                    await user_ck[0].click()
                    await page.waitFor(1000)
                    authUrl = await page.content()
                    print('成功')
    except Exception as e:
        print(e)
    finally:
        if page.isClosed():
            pass
        else:
            await page.close()
if __name__ == '__main__':
    url ='http://app.miit-eidc.org.cn/miitxxgk/gonggao/xxgk/queryCpParamPage?dataTag=Z&gid=U3119671&pc=303'
    asyncio.get_event_loop().run_until_complete(main(url))

   #代码毕竟乱,你自己看着改吧,能成功,毕竟随手写的,可以结帖了

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
ForGot_227 + 1 + 1 用心讨论,共获提升!
Pojie1999.0909 + 1 + 1 谢谢@Thanks!

查看全部评分

as614001 发表于 2021-11-12 13:44
千百度° 发表于 2021-11-12 14:01
滑动到正确位置仍然不能通过,说明轨迹被识别到机器操作了,应该修改算法为更接近人为操作的轨迹
Prozacs 发表于 2021-11-12 14:09
用pyppetter可以过
头像被屏蔽
偶尔平凡 发表于 2021-11-12 14:17
提示: 作者被禁止或删除 内容自动屏蔽
 楼主| Pojie1999.0909 发表于 2021-11-12 14:17
千百度° 发表于 2021-11-12 14:01
滑动到正确位置仍然不能通过,说明轨迹被识别到机器操作了,应该修改算法为更接近人为操作的轨迹

我不会修改算法,让其更接近人为操作。大佬求解,CB不够全给您了

点评

建议你学习一下贝尔曲线  详情 回复 发表于 2021-11-12 14:20
 楼主| Pojie1999.0909 发表于 2021-11-12 14:19

大佬,可否再详细一点?
千百度° 发表于 2021-11-12 14:20
Pojie1999.0909 发表于 2021-11-12 14:17
我不会修改算法,让其更接近人为操作。大佬求解,CB不够全给您了

建议你学习一下贝尔曲线
 楼主| Pojie1999.0909 发表于 2021-11-12 14:21
千百度° 发表于 2021-11-12 14:20
建议你学习一下贝尔曲线

多谢大佬!

点评

贝尔曲线可以过掉机器检测,但我只有易语言的例子,没有py的,需要你自行去找  详情 回复 发表于 2021-11-12 14:23
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 15:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表