关于滑块验证

前几日工作中模拟用户操作,遇到了滑块验证,虽然难度一般,但是还是做一下记录吧。只留下关于获取滑块移动距离的计算过程,其他相关,已有很多,随便都可以搜到。

先说下思路:(通过selenium获取界面并获取标签内容或者样式就跳过)

第一步就是要获取滑块的高度,因为发现,滑块的left永远都是不变的,不过我没有观察很多网站,不晓得是不是所有的都是这样,如果不是可以提前取出left值,为后边计算移动距离做准备。

第二步,获取滑块图片。通过灰化,然后取滑块4个边的RGB像素值总和作比较,因为图片经过灰化处理,所以有缺口或者突出的一边,值有明显区别。我选择的是左边作为标准,所以如果左边是缺口或者突出的,我选择刷新。如果满足左边为正常边,进行下一步。

第三步,将大图中,滑块对应的位置,从左到右应该是一长条,将这一长条用像素分为n列,取每一列的RGB像素和,相邻的两列作比较,有缺口位置的那一列和前一列差值很大,我测试的时候,差值在10000+以上,所以以此可以获取缺口位置,我是通过列表索引获取该位置横轴坐标。

第四步,通过滑块位置和缺口位置的差值计算,就可以得到,滑块所需要移动的距离值。剩下的就是需要模拟人的行为对滑块进行移动,防止被拦截。

12.11:通过在滑块接近缺口时减速、超出缺口再返回、松开滑块前加延时,可以增加成功率。

2020/7/24:附上移动参数的处理,模拟移动的代码

 # 对滑块的判断,并取出滑块的top
    def get_slide_block(self, driver):
        while True:
            # 获取滑块图片的下载地址
            a = driver.find_elements_by_id('slideBlock')

            image2 = a[0].get_attribute('src')

            css_str = driver.find_element_by_id('slideBlock').get_attribute("style")

            css_list = css_str.split(";")

            # 获取滑块的top值
            start_top = re.search(r"[0-9]{2}", css_list[2]).group()

            # 此处是发现滑块有外边框,所以加上
            start_top = int(start_top)
            start_top += 11
            start_top = start_top * 2
            start_top += 23

            # print("image1:", image1)
            image1_name = 'demo1.png'  # 滑块图片名

            # 下载滑块图片并存储到本地
            target_img = Image.open(BytesIO(requests.get(image2).content))
            target_img.save(image1_name)

            # 获取图片,并灰化
            block = cv2.imread(image1_name, 0)

            # 二值化之后的图片名称
            block_name = 'demo.jpg'

            cv2.imwrite(block_name, block)

            img = Image.open("demo.jpg")

            img_array = img.load()

            top = 0
            left = 0
            right = 0
            bottom = 0

            for i in range(23, 112):
                top += img_array[i, 23]
            for i in range(23, 112):
                left += img_array[23, i]
            for i in range(23, 112):
                right += img_array[111, i]
            for i in range(23, 112):
                bottom += img_array[i, 111]
            rgb_list = [top, left, right, bottom]
            if left != max(rgb_list):
                a = driver.find_elements_by_id('reload')
                time.sleep(random.randint(2, 4))
                a[0].click()
                time.sleep(1)
            else:
                return start_top

    # 对背景图的分析,确定需要移动的距离
    def get_slide_bkg(self, start_top, driver):
        # 获取背景大图图片的下载地址
        image2 = driver.find_element_by_id('slideBkg').get_attribute('src')

        # print("image2:", image2)

        image2_name = 'demo2.png'  # 背景大图名

        # 下载滑块图片并存储到本地
        target_img = Image.open(BytesIO(requests.get(image2).content))
        target_img.save(image2_name)

        # 获取图片,并灰化
        block = cv2.imread(image2_name, 0)

        # 二值化之后的图片名称
        block_name = 'demo2.jpg'

        cv2.imwrite(block_name, block)

        img = Image.open("demo2.jpg")

        img_array = img.load()

        rgb_list = []

        # 将滑块对应的区域,按像素分成n列,获取每列像素和,差距最大的两列为缺口位置
        for i in range(0, 680):
            left = 0
            for j in range(start_top, start_top + 88):
                left += img_array[i, j]
            rgb_list.append(left)
        for i in range(len(rgb_list) - 1):
            if rgb_list[i] - rgb_list[i + 1] > 10000:
                dis = (i + 1 - 66) / 2
                #  讲需要移动的距离返回
                return int(dis)

 # 获取移动参数   分割移动距离,放入列表
    def get_track(self, distance):
        track = []
        res = 0
        current = 0
        mid = distance * 4 / 5
        t = 0.2
        v = 0
        while current < distance:
            if current < mid:
                a = 2
            else:
                a = -3
            v0 = v
            v = v0 + a * t
            move = v0 * t + 1 / 2 * a * t * t
            current += move
            track.append(round(move))
        print("获取移动参数正常...")
        return track

    # 移动滑块,完成验证
    def let_slide_block_move(self, start_top, driver):
        button = driver.find_element_by_xpath('//*[@id="tcaptcha_drag_button"]')
        dis = self.get_slide_bkg(start_top, driver)
        track = self.get_track(dis)
        # time.sleep(random.randint(1, 3))

        # 移动滑块
        action = ActionChains(driver)
        action.click_and_hold(button).perform()
        action.reset_actions()  # 清除之前的action
        t = 0
        #   遍历移动参数列表,完成移动
        for i in track:
            if len(track) - t < 5:
                time.sleep(random.randint(500, 600) / 1000)
            action.move_by_offset(xoffset=i, yoffset=0).perform()
            action = ActionChains(driver)
            t += 1
        imitate = ActionChains(driver).move_by_offset(xoffset=-1, yoffset=0)
        time.sleep(random.uniform(0.001, 0.007))
        imitate.perform()
        time.sleep(random.randint(6, 10) / 10)
        imitate.perform()
        time.sleep(random.uniform(0.001, 0.009))
        imitate.perform()
        time.sleep(random.uniform(0.001, 0.006))
        imitate.perform()
        time.sleep(random.uniform(0.001, 0.005))
        imitate.perform()
        time.sleep(random.uniform(0.01, 0.02))
        ActionChains(driver).move_by_offset(xoffset=1, yoffset=0).perform()

        # 放开圆球
        time.sleep(3)
        action.release().perform()
        time.sleep(random.randint(1, 3))
        # 点击确定

        print("拖动正常...")
        return driver
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值