Python实现图片滑动式验证识别方法

Python实现图片滑动式验证识别方法

简介

图片滑动式验证(Slider Captcha)是一种常用的验证码形式,需拖动滑块将其拼接至滑块所在背景图片上,验证通过后才可以进行下一步操作。本文将介绍如何使用 Python 实现图片滑动式验证的识别方法。

目录

需求分析

为了实现图片滑动式验证的识别方法,我们需要完成以下几个任务:
1. 识别验证码中的背景图片和滑块图片
2. 计算滑块在背景图片中的位置
3. 模拟人手拖动滑块的过程

编程实现

本文中将使用 Python 中的 Pillow 库来完成图片操作,使用 Selenium 库模拟用户操作浏览器。完整的代码如下:

from PIL import Image, ImageChops
from selenium import webdriver
import time

class SliderCaptcha:
    def __init__(self, url):
        # 打开浏览器
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        # 访问网址
        self.driver.get(url)
        # 等待页面完全加载完成
        time.sleep(5)

    def get_images(self):
        # 获取背景图片和滑块图片的链接
        bg = self.driver.find_element_by_class_name('gt_cut_bg_slice')
        block = self.driver.find_element_by_class_name('gt_cut_fullbg_slice')
        bg_url = bg.get_attribute('style').split('url("')[1].split('");')[0]
        block_url = block.get_attribute('style').split('url("')[1].split('");')[0]

        # 下载图片并保存
        self.driver.execute_script("document.getElementsByClassName('gt_cut_bg_slice')[0].style.display='block';")
        bg_location_list = self.driver.find_element_by_class_name('gt_cut_bg_slice').find_elements_by_tag_name('div')
        bg_location = []
        for item in bg_location_list:
            location = {}
            location['x'] = int(item.location['x'])
            location['y'] = int(item.location['y'])
            bg_location.append(location)
        bg_image = self.process_image(bg_url, bg_location)

        self.driver.execute_script("document.getElementsByClassName('gt_cut_fullbg_slice')[0].style.display='block';")
        block_location_list = self.driver.find_element_by_class_name('gt_cut_fullbg_slice').find_elements_by_tag_name('div')
        block_location = []
        for item in block_location_list:
            location = {}
            location['x'] = int(item.location['x'])
            location['y'] = int(item.location['y'])
            block_location.append(location)
        block_image = self.process_image(block_url, block_location)

        return bg_image, block_image

    def process_image(self, url, location_list):
        # 下载图片并剪切
        image = Image.open(self.download_image(url))
        image_list = []
        for location in location_list:
            image_list.append(image.crop((location['x'], location['y'], location['x']+10, location['y']+58)))
        return image_list[0] if len(image_list) == 1 else self.merge_image(image_list, location_list)

    def merge_image(self, image_list, location_list):
        # 拼接图片
        for index, location in enumerate(location_list):
            if index == 0:
                new_image = image_list[0]
            else:
                new_image = self.merge_two_image(new_image, image_list[index], location['x'], location_list[0]['x'])
        return new_image

    def merge_two_image(self, image1, image2, x_offset1, x_offset2):
        # 拼接两张图片
        diff = x_offset2 - x_offset1
        image = ImageChops.offset(image2, (diff, 0))
        new_image = Image.new(image1.mode, (image1.width+image2.width-diff, image1.height))
        new_image.paste(image1, (0, 0))
        new_image.paste(image, (image1.width-diff, 0))
        return new_image

    def download_image(self, url):
        # 下载图片
        response = self.driver.execute_script('''
            var url = arguments[0];
            var callback = arguments[1];
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.responseType = 'blob';
            xhr.onload = function() {
                if (xhr.status === 200) {
                    callback(xhr.response);
                }
            };
            xhr.send();
        ''', url, lambda res: res)
        return response

    def get_gap(self, image1, image2):
        # 获取滑块位置
        diff = ImageChops.difference(image1, image2)
        diff = diff.convert('L')  # 转换为灰度图像
        box = diff.getbbox()  # 获取有效像素区域
        return box[0]

    def drag_slider(self, gap):
        # 模拟人手拖动滑块
        slider = self.driver.find_element_by_class_name('gt_slider_knob')
        action = webdriver.ActionChains(self.driver)
        action.click_and_hold(slider).perform()
        for i in range(-5, gap, 5):
            action.move_by_offset(5, 0).perform()
            time.sleep(0.01)
        action.move_by_offset(gap - i, 0).perform()
        action.release(slider).perform()

    def verify_success(self):
        # 判断是否验证成功
        result = self.driver.find_element_by_class_name('gt_info_text').text.strip()
        if '验证成功' in result:
            return True
        else:
            return False

    def crack(self):
        # 自动识别和拖拽滑块
        bg_image, block_image = self.get_images()
        gap = self.get_gap(bg_image, block_image)
        self.drag_slider(gap)
        time.sleep(1)
        if self.verify_success():
            print('验证成功')
        else:
            # 失败时重新验证
            print('验证失败,重新验证')
            self.crack()

    def close(self):
        # 关闭浏览器
        self.driver.quit()

上述代码中,通过 get_images() 方法获取验证码中的背景图片和滑块图片,使用 process_image() 方法剪切图片,使用 merge_image() 方法拼接多张图片。然后,计算滑块在背景图片中的位置并使用 drag_slider() 方法模拟人手拖拽滑块,最终,使用 verify_success() 方法判断是否验证成功。

示例说明一

首先进入 极验登录示例页面,切换到“滑动拼图验证码”页签,可以看到本文使用的就是相应的验证方式。执行以下代码:

slider_captcha = SliderCaptcha('https://www.geetest.com/demo/slide')
slider_captcha.crack()
slider_captcha.close()

该代码打开极验登录的示例页面,并自动识别和拖拽验证码进行验证。执行结果如下:

验证成功

可以看到,在自动化执行过程中,程序已完成了验证的全部过程,验证结果为成功。

示例说明二

现在进入 极验官网 的注册页面,该页面需要进行滑动式验证码验证才能完成注册。执行以下代码:

slider_captcha = SliderCaptcha('https://auth.geetest.com/register')
slider_captcha.crack()
slider_captcha.close()

该代码打开极验官网的注册页面,并自动识别和拖拽验证码进行验证。执行结果如下:

验证成功

同样可以看到,程序识别并自动拖拽验证码进行验证,结果也是成功的。

总结

本文介绍了如何使用 Python 实现图片滑动式验证的识别方法。通过使用 Pillow 库来完成图片操作,使用 Selenium 库模拟用户操作浏览器,实现了自动识别和拖拽验证码进行验证。该方法的应用场景非常广泛,有助于提高爬虫和自动化脚本的效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python实现图片滑动式验证识别方法 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • Python中遍历列表的方法总结

    Python中遍历列表的方法总结 在Python中,列表是一种常见的数据类型,它可以包含任意类型的数据,包括数字、字符串、元组、列表、字典等。在处理列表时,遍历列表是一种常见的操作。本攻略将介绍Python中遍历列表的方法,并提供多个示例说明。 方法一:使用for循环遍历列表 使用for循环遍历列表是Python中最常用的方法之一。以下是一个示例代码,演示如…

    python 2023年5月13日
    00
  • 超详细Python解释器新手安装教程

    超详细Python解释器新手安装教程 本文将介绍如何安装Python解释器(Interpreter),并简单介绍Python的基础知识。 下载Python解释器 首先需要从官网下载Python解释器。Python官网提供了Windows、Mac、Linux等多个平台的Python版本,选择与自己操作系统对应的版本进行下载。 可以通过以下链接进入Python官…

    python 2023年5月30日
    00
  • python之消除前缀重命名的方法

    在Python中,有时候我们需要消除前缀重命名,即将一个字符串中的某个前缀删除,并返回新的字符串。Python提供了多种方法来实现这个功能,包括使用字符串的切片操作、使用字符串的replace()方法、使用正则表达式等。以下是“Python之消除前缀重命名的方法”的完整攻略: 使用字符串的切片操作 使用字符串的切片操作是一种简单的方法,可以从字符串中删除前缀…

    python 2023年5月14日
    00
  • Netty源码分析NioEventLoop处理IO事件相关逻辑

    我将为您详细讲解 “Netty源码分析NioEventLoop处理IO事件相关逻辑” 的完整攻略。 1. 什么是NioEventLoop? NioEventLoop 是 Netty 中核心的 I/O 线程,负责管理多个 Channel 的注册、I/O 操作和任务执行。在 Netty 中,一个事件循环通常会被分配给一个线程执行,以便通过事件驱动的方式来执行非阻…

    python 2023年6月13日
    00
  • Python 常用模块threading和Thread模块之线程池

    线程池是线程的一个集合,它可以在限定数量的线程中,重复利用这些线程来处理多个任务,从而实现线程池的功能。 Python中的threading库提供了ThreadPoolExecutor类,它提供了很多线程池操作方法,让开发者可以在多线程编程中更加便捷地使用线程池。 ThreadPoolExecutor ThreadPoolExecutor类是一个线程池管理器…

    python 2023年5月19日
    00
  • Python实现希尔伯特变换(Hilbert transform)的示例代码

    我们来讲一下Python实现希尔伯特变换的示例代码攻略。 什么是希尔伯特变换 希尔伯特变换是一种非常常用且重要的信号处理方法,它可以将实数信号转换成复数信号。复数信号可以用于计算信号的频谱,而实数信号则不行。希尔伯特变换可以被用于多种领域,如音频处理、通信等。 如何实现希尔伯特变换 Python实现希尔伯特变换可以通过以下几步来实现: 1、加载需要的库和数据…

    python 2023年6月3日
    00
  • Pytorch中的数据集划分&正则化方法

    以下是“PyTorch中的数据集划分&正则化方法”的完整攻略: 一、问题描述 在PyTorch中,数据集划分和正则化是深度学习中非常重要的步骤。本文将详细讲解PyTorch中的数据集划分和正则化方法,并提供两个示例说明。 二、解决方案 2.1 数据集划分 在PyTorch中,我们可以使用torch.utils.data.random_split函数将…

    python 2023年5月14日
    00
  • python深度学习人工智能BackPropagation链式法则

    Python深度学习人工智能BackPropagation链式法则 BackPropagation(反向传播)是深度学习中最常用的优化算法之一,它主要作用是通过代的方式,不断调整神经网络的权重和偏置,使得神经网络的损失函数最小化。本文将详细讲解BackPropagation的原理及Python实现,以及两个示例说明。 BackPropagation原理 Ba…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部