攻克滑动拼图反爬:Python 高效爬取网页图片实战案例

一、滑动拼图反爬核心原理剖析

在编写代码前,我们必须先理解滑动拼图验证码的工作机制,这是精准破解的关键:

  1. 前端渲染逻辑 :网站加载验证码时,会生成两张图片 ------完整背景图带缺口的滑块图,缺口位置随机生成;
  2. 验证规则:用户需要用鼠标拖动滑块,精准对齐背景图的缺口,前端会记录滑动轨迹、速度、停留时间等行为数据;
  3. 反爬检测点 :单纯的机械滑动会被识别为机器行为,网站会校验滑动轨迹是否拟人滑块位置是否精准请求参数是否合法三大核心指标;
  4. 验证流程:拖动滑块→前端校验位置→服务器验证通过→解除反爬限制→开放数据访问。

传统爬虫无法模拟拟人滑动和缺口识别,这也是滑动拼图能有效拦截自动化程序的核心原因。

二、实战环境搭建与依赖库安装

本次实战基于 Python 3.8 + 版本,核心使用Selenium 模拟浏览器操作、OpenCV 识别图片缺口、requests爬取目标图片,同时搭配 ChromeDriver 实现浏览器驱动。

1. 核心依赖库安装

打开命令行执行以下安装命令:

bash

运行

plain 复制代码
# 模拟浏览器操作
pip install selenium==4.15.0
# 图片处理与缺口识别
pip install opencv-python==4.8.0
# 网络请求与随机数生成
pip install requests numpy random

2. ChromeDriver 配置

  1. 查看本地 Chrome 浏览器版本,下载对应版本的 ChromeDriver;
  2. 将 ChromeDriver.exe 放置在 Python 根目录,或在代码中指定驱动路径。

注意:建议使用 Chrome 110 + 版本,保证驱动兼容性。

三、整体实现思路

本次实战分为五大核心步骤,形成闭环解决方案:

  1. 初始化浏览器,访问目标网站,加载滑动拼图验证码;
  2. 截取验证码背景图和滑块图,保存到本地;
  3. 基于 OpenCV 模板匹配算法,识别缺口的横向坐标;
  4. 生成拟人滑动轨迹,模拟鼠标拖动滑块完成验证;
  5. 验证通过后,定位网页图片元素,批量高效爬取并保存图片。

四、完整代码实现与分步解析

步骤 1:初始化浏览器与访问目标页面

首先封装浏览器初始化函数,关闭 Chrome 的自动化检测特征,避免被网站识别为爬虫。

python

运行

plain 复制代码
import cv2
import numpy as np
import random
import time
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import os

# 创建图片保存文件夹
if not os.path.exists("captcha_img"):
    os.mkdir("captcha_img")
if not os.path.exists("target_imgs"):
    os.mkdir("target_imgs")

def init_browser():
    """初始化Chrome浏览器,规避反爬检测"""
    chrome_options = Options()
    # 关闭自动化提示
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    # 禁用图片加载(可选,提升速度)
    # chrome_options.add_argument('--blink-settings=imagesEnabled=false')
    # 初始化驱动
    driver = webdriver.Chrome(options=chrome_options)
    # 修改浏览器特征,隐藏webdriver属性
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
        'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
    })
    driver.maximize_window()
    return driver

# 初始化浏览器并访问目标网站
driver = init_browser()
# 替换为你要爬取的带滑动拼图验证的网站
target_url = "https://www.test-spider.com/slider-captcha"
driver.get(target_url)
time.sleep(2)

步骤 2:截取验证码图片

通过 Selenium 定位背景图和滑块元素,截取图片并保存,为缺口识别做准备。

python

运行

plain 复制代码
def get_captcha_img(driver):
    """获取滑动拼图的背景图和滑块图"""
    # 定位背景图和滑块元素(根据实际网页修改选择器)
    bg_img = driver.find_element(By.CLASS_NAME, "captcha-bg")
    slider_img = driver.find_element(By.CLASS_NAME, "captcha-slider")
    
    # 截取图片
    bg_img.screenshot("captcha_img/bg.png")
    slider_img.screenshot("captcha_img/slider.png")
    time.sleep(1)
    return "captcha_img/bg.png", "captcha_img/slider.png"

# 获取验证码图片
bg_path, slider_path = get_captcha_img(driver)

步骤 3:OpenCV 识别缺口坐标

这是核心步骤!使用 OpenCV 的模板匹配算法,将滑块图与背景图对比,精准计算缺口的横向偏移量。

python

运行

plain 复制代码
def get_gap_position(bg_path, slider_path):
    """识别缺口位置,返回横向偏移坐标"""
    # 读取图片
    bg = cv2.imread(bg_path, 0)
    slider = cv2.imread(slider_path, 0)
    
    # 模板匹配:查找滑块在背景图中的位置
    result = cv2.matchTemplate(bg, slider, cv2.TM_CCOEFF_NORMED)
    # 获取匹配结果的最大值坐标
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    
    # 缺口横坐标(根据实际图片尺寸微调)
    gap_x = max_loc[0]
    print(f"识别到缺口横坐标:{gap_x}")
    return gap_x

# 获取缺口位置
gap_x = get_gap_position(bg_path, slider_path)

步骤 4:模拟拟人滑动轨迹

机器匀速滑动会被直接拦截,我们需要生成先加速后减速、带微小抖动的拟人轨迹,模拟人类拖动行为。

python

运行

plain 复制代码
def get_slide_track(distance):
    """生成拟人滑动轨迹:返回每一步的偏移量"""
    track = []
    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 + 0.5 * a * t * t
        current += move
        # 添加微小抖动,更拟人
        track.append(round(move + random.uniform(-0.5, 0.5), 2))
    return track

def slide_captcha(driver, gap_x):
    """模拟滑动拼图验证"""
    # 定位滑块元素
    slider = driver.find_element(By.CLASS_NAME, "slider-btn")
    # 生成滑动轨迹
    track = get_slide_track(gap_x - 10)  # 微调偏移量
    
    # 按住滑块
    ActionChains(driver).click_and_hold(slider).perform()
    time.sleep(random.uniform(0.2, 0.5))
    
    # 按照轨迹滑动
    for step in track:
        ActionChains(driver).move_by_offset(xoffset=step, yoffset=0).perform()
        time.sleep(random.uniform(0.005, 0.01))
    
    # 随机停顿后释放
    time.sleep(random.uniform(0.3, 0.6))
    ActionChains(driver).release().perform()
    time.sleep(2)
    
    # 判断验证是否成功
    try:
        driver.find_element(By.CLASS_NAME, "captcha-success")
        print("滑动验证成功!")
        return True
    except:
        print("滑动验证失败,重试中...")
        return False

# 执行滑动验证,最多重试3次
retry_count = 0
while retry_count < 3:
    if slide_captcha(driver, gap_x):
        break
    retry_count += 1
    time.sleep(1)

步骤 5:验证通过后批量爬取网页图片

滑动验证成功后,反爬限制解除,我们可以直接定位网页中的图片元素,批量下载并保存。

python

运行

plain 复制代码
def download_img(img_url, save_path):
    """下载单张图片"""
    try:
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
        }
        response = requests.get(img_url, headers=headers, timeout=10)
        with open(save_path, "wb") as f:
            f.write(response.content)
        return True
    except Exception as e:
        print(f"图片下载失败:{e}")
        return False

def crawl_target_imgs(driver):
    """批量爬取网页图片"""
    # 定位所有图片元素(根据实际网页修改选择器)
    img_elements = driver.find_elements(By.XPATH, '//div[@class="img-list"]//img')
    print(f"共找到{len(img_elements)}张图片")
    
    success_count = 0
    for index, img in enumerate(img_elements):
        # 获取图片真实地址
        img_url = img.get_attribute("src")
        if not img_url or img_url.startswith("data:image"):
            continue
        save_path = f"target_imgs/img_{index+1}.jpg"
        # 下载图片
        if download_img(img_url, save_path):
            success_count += 1
            print(f"第{success_count}张图片下载完成")
        time.sleep(random.uniform(0.5, 1))  # 随机延时,避免请求过快
    
    print(f"图片爬取完成,成功下载{success_count}/{len(img_elements)}张")

# 执行图片爬取
crawl_target_imgs(driver)

# 关闭浏览器
driver.quit()

五、代码优化与反爬规避进阶技巧

以上代码可实现基础的滑动拼图破解与图片爬取,在实际生产环境中,我们可以通过以下方式提升稳定性:

  1. 动态 UA 切换:每次请求更换 User-Agent,避免 UA 被拉黑;
  2. 代理 IP 池:使用高匿代理 IP,解决 IP 封禁问题(推荐使用亿牛云爬虫代理);
  3. 轨迹优化:增加随机停顿、轻微上下偏移,更贴合人类滑动习惯;
  4. 图片预加载:提前缓存验证码图片,提升识别速度;
  5. 异常重试机制:针对验证失败、图片加载失败等场景,增加自动重试逻辑。

六、总结

滑动拼图反爬是前端人机验证的基础形态,其核心难点在于缺口精准识别拟人轨迹模拟。本文通过 Python+OpenCV+Selenium 的技术组合,实现了从验证破解到图片爬取的全流程自动化:OpenCV 解决了机器视觉识别问题,拟人滑动轨迹绕过了前端行为检测,最终实现高效、稳定的网页图片爬取。

对于爬虫开发者而言,掌握滑动拼图破解只是起点,后续可延伸学习极验验证码、文字点选、无感验证等更复杂的反爬机制。在技术实践中,始终坚守合规底线,才能让爬虫技术真正发挥数据采集与分析的价值。

相关推荐
煜磊2 小时前
C/C++语言部署安装_C/C++Api学习
开发语言·c++
低频电磁之道2 小时前
C++ 源码文本格式规范
开发语言·c++
大尚来也3 小时前
Java反射机制:从底层原理到Spring框架的深度实践
开发语言
꧁꫞꯭零꯭点꯭꫞꧂3 小时前
前端面试题3
开发语言·前端·javascript
共享家95273 小时前
C++核心之多线程
开发语言·c++
南境十里·墨染春水3 小时前
C++ 笔记 function 函数包装器模板
开发语言·c++·笔记
MC皮蛋侠客3 小时前
C++中使用Redis指南:基于redis-plus-plus库
开发语言·c++·redis