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日

相关文章

  • Django ORM 查询管理器源码解析

    Django ORM是Django框架中的一个重要组件,用于管理数据库。其中,查询管理器是ORM的一个重要部分,用于查询数据库中的数据。以下是Django ORM查询管理器源码解析: 查询管理器基本用法 查询管理器是Django ORM中的一个对象,用于查询数据库中的数据。以下是查询管理器的基本用法: from django.db import models…

    python 2023年5月14日
    00
  • Python探索之实现一个简单的HTTP服务器

    Python探索之实现一个简单的HTTP服务器 简介 在web开发中,服务器是一个非常关键的组件,它可以解析来自浏览器的HTTP请求,并返回相应的HTML文件。Python作为一门强大的编程语言,具有内置的Web服务器组件,不需要任何第三方库即可实现基本的HTTP服务器功能。 环境准备 使用Python内置的HTTPServer模块,不需要额外的库依赖。 实…

    python 2023年5月19日
    00
  • Python制作微信机器人教程详解

    Python制作微信机器人教程详解 介绍 微信机器人是一种非常常见的应用场景,它可以自动回复信息、管理群组、自动发送消息等等。Python语言具有简单易学、灵活性强等特点,成为人们实现微信机器人最常用的编程语言之一。 本教程将介绍如何使用Python编写微信机器人,并基于itchat库介绍微信机器人的开发。 步骤 准备环境 首先我们需要安装Python和it…

    python 2023年5月23日
    00
  • Python numpy中np.random.seed()的详细用法实例

    关于Python numpy中np.random.seed()的用法,我有以下详细的攻略。 1. 什么是np.random.seed() np.random.seed()是用于重现随机样本的numpy函数。在数据分析中,我们通常需要生成随机样本来模拟数据或者用于模型的训练,而每次运行代码时,随机样本都会发生变化,这可能会导致结果不一致。为了解决这个问题,可以…

    python 2023年6月3日
    00
  • Python中字符串切片详解

    我来为你详细讲解“Python中字符串切片详解”的完整攻略。 一、什么是字符串切片 Python中的字符串切片是指对一个字符串对象进行切片,获取其中的一部分子字符串,常用于从字符串中获取特定位置的字符或子串。 Python中的字符串可以被视为一种序列类型,因此序列类型中所有适用的操作,都可以用于字符串切片。 二、字符串切片的语法 Python中的字符串切片语…

    python 2023年6月5日
    00
  • Python实现的基于优先等级分配糖果问题算法示例

    以下是关于“Python实现的基于优先等级分配糖果问题算法示例”的完整攻略: 简介 糖果分配问题是一个经典的问题,通常涉及到将一定数量的糖果分配给一组孩子。在这个问题中,每个孩子都有一个优先级,我们需要按照优先级分配糖果,同时确保每个孩子至少分配到一个糖果。本教程将介绍如何使用Python实现基于优先等级分配糖果问题的算法。 步骤 1. 定义函数 首先,我们…

    python 2023年5月14日
    00
  • python+pyqt5实现KFC点餐收银系统

    下面我将详细讲解“python+pyqt5实现KFC点餐收银系统”的完整攻略,让大家可以轻松实现该项目。 确定项目需求 在开始项目前,需要明确项目的需求和功能。例如,KFC点餐收银系统需要实现以下功能: 显示菜单列表 选择餐品和数量 显示购物车中的餐品和总价 结算并生成订单 确定技术栈 根据需求,在实现该项目时,我们可采用以下技术栈: Python 3.6或…

    python 2023年5月30日
    00
  • 如何使用Python连接和操作SQLite数据库?

    在Python中,可以使用sqlite3模块连接和操作SQLite数据库。以下是Python使用sqlite3模块连接和操作SQLite数据库的完整攻略,包括连接SQLite数据库、表、插入数据、查询数据、更新数据、删除数据等操作。 连接SQLite数据库 在Python中,可以使用sqlite3模块连接SQLite。以下是连接SQLite数据库的基本语法:…

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