告别手动拖动!Python+dddocr自动化破解多缺口滑块

本文适合新手小白,带你一步步实现自动化通过多缺口滑块验证,助你轻松应对反爬虫难题!

一、什么是滑块验证?

滑块验证是一种常见的反爬虫手段,用户需要按住滑块拖动到指定位置,才能通过验证。多缺口滑块验证则是在背景图上有多个缺口,滑块需要精确拖动到正确的缺口位置。

手动操作很简单,但自动化通过却难倒了不少爬虫新手。本文将带你用 Python + DrissionPage 实现自动化滑块验证。


二、核心思路

  1. 识别滑块和背景图:获取页面上的滑块和背景图片。
  2. 识别缺口位置:用 OCR 或图像处理算法识别缺口的准确位置。
  3. 模拟人类拖动滑块:用代码模拟鼠标按下、移动、释放,完成滑块验证。

三、代码实战

1. 环境准备

  • Python 3.8+
  • DrissionPage
  • pillow(用于图片处理)
  • ddddocr(滑块识别)
bash 复制代码
pip install DrissionPage pillow ddddocr

2. 主要代码结构

2.1 滑块识别核心:recognize_slider_distance

滑块验证的关键是如何准确识别滑块需要移动的距离。下面详细讲解 recognize_slider_distance 的实现原理和代码:

python 复制代码
import base64
import numpy as np
from PIL import Image
import io
import ddddocr

def base64_decode(str):
    return base64.b64decode(str)

def slider_puzzle_qg(p_puzzle_path: str = ''):
    """
    将小拼图去除透明边缘,返回处理后的base64图片和位置信息
    """
    image = Image.open(p_puzzle_path)
    width, height = image.size
    pixels = image.load()
    _a = 0  # 顶部透明行数
    _b = 0  # 有效拼图高度
    _c = 0  # 底部透明行数
    k = []  # 有效像素
    buffered = io.BytesIO()
    for x in range(height):
        data_pixel = []
        for y in range(width):
            r, g, b, a = pixels[y, x]
            data_pixel += [(r, g, b, a)]
        NumPy_data_pixel = np.array(data_pixel)
        if np.all(NumPy_data_pixel == 0):
            if _b == 0:
                _a += 1
            else:
                if _c == 0:
                    new_image = Image.new('RGBA', (width, _b), color=(0, 0, 0, 0))
                    new_image.putdata(k)
                    new_image.save(buffered, format="PNG")
                _c += 1
        else:
            _b += 1
            k += data_pixel
    return {
        '最顶层-顶层距离': _a,
        '中间层-拼图的高度': _b,
        '最底层-底层距离': _c,
        'base64': base64.b64encode(buffered.getvalue()).decode()
    }

def background_cutting(b_puzzle_path: str = '', b_size_h: int = 0, p_size_h: int = 0):
    """
    按小拼图的高度切割背景图,返回base64
    """
    image = Image.open(b_puzzle_path)
    width, height = image.size
    left, right = 0, width
    top, bottom = b_size_h, b_size_h + p_size_h
    cropped_image = image.crop((left, top, right, bottom))
    buffered = io.BytesIO()
    cropped_image.save(buffered, format="PNG")
    return {'base64': base64.b64encode(buffered.getvalue()).decode()}

def recognize_slider_distance(xiaopintu_path, beijingtu_path):
    """
    识别滑块需要移动的距离
    :param xiaopintu_path: 小拼图路径
    :param beijingtu_path: 背景图路径
    :return: 滑动距离
    """
    det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
    xiaopintu_data = slider_puzzle_qg(p_puzzle_path=xiaopintu_path)
    beijingtu_data = background_cutting(b_puzzle_path=beijingtu_path, b_size_h=xiaopintu_data['最顶层-顶层距离'],
                                        p_size_h=xiaopintu_data['中间层-拼图的高度'])
    res1 = det.slide_match(base64_decode(beijingtu_data['base64']), base64_decode(xiaopintu_data['base64']),
                           simple_target=True)
    res1 = res1['target'][0]
    # 为了更像人类操作,可以加一点偏移
    res = res1 * 1.1 - 4
    return res

原理说明:

  • 先用 slider_puzzle_qg 去除小拼图的透明边缘,获得有效区域和高度。
  • background_cutting 按小拼图的高度切割背景图,获得滑道。
  • 用 ddddocr 的 slide_match 方法,计算小拼图在滑道中的最佳匹配位置(即缺口横坐标)。
  • 最后加一点偏移,模拟人类误差,防止被反爬虫检测。

2.2 登录与滑块拖动

下面是完整的登录与滑块拖动自动化代码示例,适合新手理解:

python 复制代码
import random
import time
import base64
from DrissionPage import Chromium, ChromiumOptions
from utils.ocr_util import recognize_slider_distance  # 上文已详细讲解
from service.logger import logger

# 创建浏览器实例
co = ChromiumOptions().set_browser_path(r'C:\Path\To\chrome.exe')
tab = Chromium().latest_tab

def base64_decode(data):
    return base64.b64decode(data + '==')

def login_with_slider(tab, username, password):
    try:
        # 1. 打开登录页面(URL已脱敏)
        tab.get('https://your-domain.com/login')
        # 2. 输入账号密码
        username_ele = tab.ele('@@tag()=input@@placeholder=请输入账号')
        password_ele = tab.ele('@@tag()=input@@placeholder=请输入密码')
        username_ele.input(username)
        password_ele.input(password)
        # 3. 点击登录按钮
        login_button = tab.ele('@@tag()=span@@text():登 录')
        login_button.click(by_js=True)

        # 4. 获取滑块和背景图片
        background_image_ele = tab.ele('@@tag()=div@@class=verify-img-panel').ele('@@tag()=img')
        gap_image_ele = tab.ele('@@tag()=div@@class=verify-sub-block').ele('@@tag()=img')
        xiaopintu_data = gap_image_ele.attr('src').split("data:image/png;base64,")[-1]
        background_img_data = background_image_ele.attr('src').split("data:image/png;base64,")[-1]
        with open('beijingtu.png', 'wb') as f:
            f.write(base64_decode(background_img_data))
        with open('xiaopintu.png', 'wb') as f:
            f.write(base64_decode(xiaopintu_data))

        # 5. 识别滑块需要移动的距离
        distance = recognize_slider_distance(xiaopintu_path="xiaopintu.png", beijingtu_path="beijingtu.png")
        tab.wait.ele_displayed('@@tag()=div@@class=verify-move-block', timeout=10)
        slider = tab.ele('@@tag()=div@@class=verify-move-block').wait.clickable(timeout=10)
        if not slider:
            logger.error('未找到滑块元素,请检查类名或页面结构')
            return False
        else:
            tab.run_js('arguments[0].style.border="2px solid red"', slider)
            logger.info(' 找到滑块元素,开始滑动')
            # 6. 获取滑块中心点坐标
            slider_rect = tab.run_js('''
                const rect = arguments[0].getBoundingClientRect();
                return {
                    x: rect.x + rect.width / 2,
                    y: rect.y + rect.height / 2
                }
            ''', slider)
            try:
                # 7. 用 JS 模拟鼠标事件拖动滑块
                tab.run_js('''
                    function simulateMouseEvent(element, eventType, x, y) {
                        const event = new MouseEvent(eventType, {
                            view: window,
                            bubbles: true,
                            cancelable: true,
                            clientX: x,
                            clientY: y
                        });
                        element.dispatchEvent(event);
                    }
                    const slider = arguments[0];
                    const startX = arguments[1];
                    const startY = arguments[2];
                    const distance = arguments[3];
                    simulateMouseEvent(slider, 'mousedown', startX, startY);
                    const segments = 5;
                    const segmentDistance = distance / segments;
                    let currentX = startX;
                    for (let i = 0; i < segments; i++) {
                        currentX += segmentDistance;
                        simulateMouseEvent(slider, 'mousemove', currentX, startY);
                    }
                    currentX -= 5;
                    simulateMouseEvent(slider, 'mousemove', currentX, startY);
                    simulateMouseEvent(slider, 'mouseup', currentX, startY);
                ''', slider, slider_rect['x'], slider_rect['y'], distance)
                logger.info(' 滑动操作已发送')
                time.sleep(1)
            except Exception as e:
                logger.error(f' 滑动出错: {e}')
                return False
        # 8. 后续验证、UKey等操作略
        return True
    except Exception as e:
        logger.error(f"登录失败,错误信息:{e}")
        return False

代码说明:

  • 步骤1-3:自动化输入账号、密码并点击登录。
  • 步骤4:获取滑块和背景图片,保存为本地文件。
  • 步骤5:调用 recognize_slider_distance 识别滑块需要移动的距离。
  • 步骤6:获取滑块元素的中心点坐标。
  • 步骤7:用 JavaScript 分段模拟鼠标拖动滑块,模拟人类操作。此处也可以使用drisionpage操作元素例如:
bash 复制代码
# 向右移动鼠标
# tab_.actions.right(distance - 10)
time.sleep(0.05)
# tab_.actions.right(10)
  • 步骤8:后续如UKey验证等可根据实际需求补充。

3. 关键技术点说明

  • 图片识别recognize_slider_distance 利用 ddddocr 的滑块识别能力,极大简化了滑块距离的计算。
  • 图片预处理:去除透明边缘、切割滑道,是提升识别准确率的关键。
  • JS 模拟鼠标事件 :直接用 JS 触发 mousedownmousemovemouseup,比传统动作链更容易绕过部分反爬虫。
  • 分段移动:模拟人手抖动,分多段移动更像真人。
  • 异常处理:每一步都要加 try/except,方便调试。

四、常见问题与排查

  1. 滑块没动?
    • 检查元素选择器是否准确。
    • 检查 JS 事件是否被页面拦截。
    • 尝试加大分段数,或调整每段距离。
  2. 识别距离不准?
    • 检查图片保存是否完整。
    • 调整识别算法参数。
    • 检查小拼图和背景图的预处理是否正确。
  3. 验证失败?
    • 检查是否有额外的行为验证(如轨迹分析、行为分析)。
    • 尝试加大拖动时间,模拟更慢的拖动。

五、总结

自动化通过多缺口滑块验证并不神秘,关键在于:

  • 正确识别滑块和缺口位置(图片预处理+滑块识别)
  • 用 JS 或动作链模拟真实拖动
  • 多调试、多尝试,遇到问题多看日志

希望这篇教程能帮你迈出自动化滑块验证的第一步!


温馨提示:请勿将本教程用于非法用途,合理合规使用自动化技术。

相关推荐
烛阴7 小时前
简单入门Python装饰器
前端·python
好开心啊没烦恼7 小时前
Python 数据分析:numpy,说人话,说说数组维度。听故事学知识点怎么这么容易?
开发语言·人工智能·python·数据挖掘·数据分析·numpy
面朝大海,春不暖,花不开8 小时前
使用 Python 实现 ETL 流程:从文本文件提取到数据处理的全面指南
python·etl·原型模式
2301_805054569 小时前
Python训练营打卡Day59(2025.7.3)
开发语言·python
万千思绪9 小时前
【PyCharm 2025.1.2配置debug】
ide·python·pycharm
微风粼粼11 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
云天徽上11 小时前
【PaddleOCR】OCR表格识别数据集介绍,包含PubTabNet、好未来表格识别、WTW中文场景表格等数据,持续更新中......
python·ocr·文字识别·表格识别·paddleocr·pp-ocrv5
你怎么知道我是队长11 小时前
python-input内置函数
开发语言·python
叹一曲当时只道是寻常12 小时前
Python实现优雅的目录结构打印工具
python
hbwhmama12 小时前
python高级变量XIII
python