Python爬虫第22节- 结合Selenium识别滑动验证码实战

目录

一、引言

二、滑动验证码原理与反爬机制

2.1 验证码原理

2.2 反爬机制

三、工程实战:滑动验证码识别全流程

3.1 工程准备

3.1.1 环境依赖

3.1.2 目标网站与验证码识别案例

3.2 核心破解流程

3.2.1 自动化打开网页与登录

3.2.2 获取验证码图片(适配缩放)

3.2.3 识别缺口左边缘

3.2.4 计算滑动距离(左边缘对齐)

3.2.5 生成自然滑动轨迹与回弹

3.2.6 按轨迹移动滑块

3.2.7 主流程整合

结语


🎬 攻城狮7号:个人主页

🔥 个人专栏: 《python爬虫教程》

⛺️ 君子慎独!

 🌈 大家好,欢迎来访我的博客!
⛳️ 此篇文章主要介绍 滑动验证码 的识别
📚 本期文章收录在《python爬虫教程》,大家有兴趣可以自行查看!
⛺️ 欢迎各位 ✔️ 点赞 👍 收藏 ⭐留言 📝!

一、引言

        随着互联网安全需求的提升,滑动验证码(Slider Captcha)已成为各大网站防止自动化攻击和恶意爬虫的主流手段之一。相比传统的字符型验证码,滑动验证码通过人机交互和行为轨迹分析,大幅提升了破解难度。对于自动化测试、数据采集和安全研究者来说,如何精准识别和模拟滑动验证码,是一项极具挑战性的工程任务。

        本章将以实际工程代码为主线,系统讲解结合Selenium知识进行滑动验证码的识别与破解流程(不懂Selenium的请自行学习前面章节),涵盖原理分析、反爬机制、核心代码实现、调试技巧、常见问题与工程实战经验,帮助读者掌握滑动验证码自动化识别的全流程。

二、滑动验证码原理与反爬机制

2.1 验证码原理

滑动验证码的基本流程是:

        (1)用户在页面上看到一张带有缺口的图片和一个可拖动的滑块。

        (2)用户需要按住滑块,将其拖动到缺口处,使图片拼合完整。

        (3)系统通过前端和后端双重校验,判断滑块是否准确对齐缺口,并分析拖动轨迹是否自然。

滑动验证码的常见类型有:

        - 拼图型滑动验证码:最常见,用户需将滑块拖到缺口处。

        - 轨迹型滑动验证码:要求用户沿特定轨迹拖动滑块。

        - 多步验证型:滑动后还需输入字符或完成其他操作。

2.2 反爬机制

滑动验证码的反爬机制主要包括:

        - 轨迹分析:检测滑块移动轨迹是否自然(加速度、抖动、停顿等)。

        - 环境检测:检测浏览器指纹、User-Agent、Cookie、Referer 等参数。

        - 图片混淆:验证码图片可能经过切片、加密、canvas 绘制等处理。

        - 行为识别:分析鼠标事件、点击频率、页面交互等行为特征。

破解滑动验证码的难点在于:

        - 缺口识别:需精准定位缺口左边缘,避免阴影、边框等干扰。

        - 轨迹模拟:需生成近似人类的加速-减速轨迹,并加入微小抖动和回弹。

        - 环境伪装:需伪装浏览器指纹、请求头等,防止被反爬机制识别。

三、工程实战:滑动验证码识别全流程

        接下来详细讲解滑动验证码识别与破解的完整工程流程。

3.1 工程准备

3.1.1 环境依赖

- Python 3.x

- Selenium

- Pillow (PIL)

- Chrome 浏览器及 ChromeDriver

安装依赖:

pip install selenium pillow

3.1.2 目标网站与验证码识别案例

        以保险公司产品查询系统( 财产保险公司自主注册产品查询V1.0.0  )为例,登录页面集成了典型的拼图型滑动验证码。验证码区域如图所示:

下面是实现滑动验证码识别的动图(滑动的速度可以自行调整):

        那么我们是如何实现的呢,那请看下面内容分析

3.2 核心破解流程

3.2.1 自动化打开网页与登录

        首先,使用 Selenium 自动化打开目标网页,随便输入用户名和密码,点击登录按钮,触发滑动验证码弹窗。下面是定位用户名密码框输入模拟登录操作

from selenium import webdriver  # 导入Selenium库,用于自动化浏览器操作from selenium.webdriver.common.by import By  # 用于元素定位from selenium.webdriver.support.ui import WebDriverWait  # 显式等待,确保元素加载完成from selenium.webdriver.support import expected_conditions as EC  # 等待条件from selenium.webdriver import ActionChains  # 用于模拟鼠标拖动等复杂操作from PIL import Image, ImageDraw  # 图像处理库,用于截图和画辅助线import time  # 时间控制class CrackSlider():def __init__(self):self.url = "https://cxcx.iachina.cn/"  # 目标网站self.chrome_options = webdriver.ChromeOptions()  # 创建Chrome配置对象self.chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])  # 隐藏自动化标识,降低被检测风险self.browser = webdriver.Chrome(options=self.chrome_options)  # 启动Chrome浏览器self.browser.maximize_window()  # 最大化窗口,防止截图区域不全self.wait = 2  # 默认等待时间(秒)def open(self):self.browser.get(self.url)  # 打开目标网页time.sleep(self.wait)  # 等待页面加载def input_login_info(self):myname = self.browser.find_element(By.XPATH, "/html/body/form/div/div[2]/div[1]/input[1]")  # 定位用户名输入框myname.send_keys("1111")  # 输入用户名mycode = self.browser.find_element(By.XPATH, '//*[@id="passWord"]')  # 定位密码输入框mycode.send_keys("1111")  # 输入密码time.sleep(2)  # 等待输入完成def click_login(self):button = self.browser.find_element(By.XPATH, '/html/body/form/div/div[3]/input[5]')  # 定位登录按钮button.click()  # 点击登录time.sleep(2)  # 等待滑动验证码弹出

实现思路与设计原因:

        - 采用Selenium自动化浏览器,能够真实模拟用户操作,绕过大部分前端反爬机制。

        - 显式等待和sleep结合,确保页面元素加载和渲染完成,避免截图黑屏或元素未找到。

        - 最大化窗口和隐藏自动化标识,有助于提升截图准确性和通过率。

3.2.2 获取验证码图片(适配缩放)

        验证码图片通常经过缩放或高分屏渲染,需获取 devicePixelRatio 并裁剪出验证码区域。

screenshot_all.png 

 def get_captcha_image(self, filename):wait = WebDriverWait(self.browser, 10)  # 显式等待,确保验证码图片元素可见element = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="slideBar"]/div/div[1]/div[2]/div[2]/div[1]')))time.sleep(2)  # 等待图片渲染,防止截图为黑色self.device_pixel_ratio = self.browser.execute_script('return window.devicePixelRatio')  # 获取浏览器缩放比例location = element.location  # 获取验证码图片左上角坐标(页面坐标)size = element.size  # 获取验证码图片宽高left = location['x'] * self.device_pixel_ratio  # 左坐标(页面坐标*缩放)top = location['y'] * self.device_pixel_ratio  # 上坐标right = left + size['width'] * self.device_pixel_ratio  # 右坐标bottom = top + size['height'] * self.device_pixel_ratio  # 下坐标self.browser.save_screenshot("screenshot_all.png")  # 截取全屏im = Image.open("screenshot_all.png")  # 打开截图img = im.crop((left, top, right, bottom))  # 裁剪验证码区域img.save(filename)  # 保存验证码图片return img  # 返回PIL.Image对象

实现思路与设计原因:

        - 通过显式等待和sleep,确保验证码图片已完全渲染,避免截图黑屏。

        - 获取devicePixelRatio,适配高分屏和浏览器缩放,保证裁剪区域与实际验证码一致。

        - 先全屏截图再裁剪,兼容所有浏览器和页面布局。

3.2.3 识别缺口左边缘

        通过对比"无缺口"和"有缺口"两张图片,遍历像素,找出差异最大的区域,确定缺口左边缘。

 def get_gap(self, image1, image2):beforecode = image1.convert("L")  # 转为灰度图,简化像素对比aftercode = image2.convert("L")  # 转为灰度图threshold = 60  # 像素差阈值,调节灵敏度width = beforecode.size[0]  # 图片宽度height = beforecode.size[1]  # 图片高度diff_w = []  # 存储所有差异点的横坐标for h in range(0, height):  # 遍历每一行for w in range(int(round(width/3,0)), width):  # 从1/3宽度开始,避开左侧干扰beforepixel = beforecode.getpixel((w,h))  # 获取无缺口像素afterpixel = aftercode.getpixel((w,h))  # 获取有缺口像素if abs(beforepixel - afterpixel) > threshold:  # 差异大于阈值diff_w.append(w)  # 记录差异点横坐标if diff_w:gap_left = min(diff_w)  # 差异区间左边界gap_right = max(diff_w)  # 差异区间右边界gap_center = (gap_left + gap_right) // 2  # 取中心点return gap_left, gap_center  # 返回左边缘和中心return 0, 0  # 未找到则返回0

实现思路与设计原因:

        - 灰度化处理简化像素对比,提升识别速度和鲁棒性。

        - 只遍历右侧2/3区域,避开左侧logo或干扰元素。

        - 统计所有差异点,取最左为gap_left,最右为gap_right,中心为gap_center。

        - 返回gap_left用于滑块左边缘对齐,gap_center用于调试和可视化。

3.2.4 计算滑动距离(左边缘对齐)

        滑块左边缘应对齐缺口左边缘,滑动距离为:

    gap_left, gap_center = self.get_gap(image1, image2)  # 获取缺口左边缘和中心captcha_left = captcha_element.location['x'] * self.device_pixel_ratio  # 验证码图片左上角页面坐标gap_left_page = captcha_left + gap_left  # 缺口左边缘页面坐标slider_left = slider_location['x'] * self.device_pixel_ratio  # 滑块左边缘页面坐标move_distance = gap_left_page - slider_left  # 实际需要滑动的距离

实现思路与设计原因:

        - 所有坐标都统一为页面坐标并乘以devicePixelRatio,避免缩放误差。

        - 滑块左边缘对齐缺口左边缘,符合大多数滑动验证码的判定逻辑。

        - move_distance为正,表示向右滑动。

3.2.5 生成自然滑动轨迹与回弹

        轨迹需模拟人类加速-减速运动,并在末尾加入回弹和微小抖动。

    def get_track(self, distance):if distance <= 0:return [0]  # 距离为0直接返回track = []  # 存储每次移动的距离current = 0  # 当前位移mid = distance * 4 / 5  # 前4/5为加速,后1/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))  # 记录本次移动if len(track) > 0:track[-1] = int(round(distance - sum(track[:-1])))  # 修正最后一步if abs(sum(track) - distance) > 1:track.append(int(distance - sum(track)))  # 再次修正return track

实现思路与设计原因:

        - 轨迹分为加速和减速两段,模拟人手自然运动。

        - 每步位移用物理公式计算,提升轨迹真实性。

        - 最后一步修正,确保总距离精确。

        - 可在轨迹末尾加微小抖动和回弹,进一步提升"人味"。

轨迹末尾加回弹:

track = self.get_track(move_distance)  # 生成主轨迹
track.extend([3, -2, 1, -1])  # 加入回弹和微调

3.2.6 按轨迹移动滑块

    def move_to_gap(self, slider, tracks):actions = ActionChains(self.browser)  # 创建动作链actions.click_and_hold(slider).perform()  # 按住滑块for x in tracks:actions.move_by_offset(xoffset=x, yoffset=0).perform()  # 拖动滑块time.sleep(1)  # 停顿,模拟人类松手前的停留actions.release().perform()  # 松开滑块,完成验证

实现思路与设计原因:

        - 使用ActionChains模拟鼠标按住、拖动、松开全过程。

        - 每步移动后立即执行,模拟真实鼠标拖动。

        - 松手前适当停顿,提升通过率。

3.2.7 主流程整合

beforecode.png(获取的无缺口图片)

 aftercode.png(获取的缺口图片)

    def crack(self):self.open()  # 打开网页self.input_login_info()  # 输入用户名和密码self.click_login()  # 点击登录,弹出验证码image1 = self.get_captcha_image('beforecode.png')  # 获取无缺口图片slider = self.get_slider()  # 获取滑块元素slider.click()  # 点击滑块,显示缺口time.sleep(3)  # 等待缺口图片渲染image2 = self.get_captcha_image('aftercode.png')  # 获取带缺口图片gap_left, gap_center = self.get_gap(image1, image2)  # 识别缺口左边缘和中心captcha_element = self.browser.find_element(By.XPATH, '//*[@id="slideBar"]/div/div[1]/div[2]/div[2]/div[1]')  # 验证码元素captcha_left = captcha_element.location['x'] * self.device_pixel_ratio  # 验证码左上角页面坐标gap_left_page = captcha_left + gap_left  # 缺口左边缘页面坐标slider_location = slider.location  # 滑块左上角页面坐标slider_size = slider.size  # 滑块宽高slider_left = slider_location['x'] * self.device_pixel_ratio  # 滑块左边缘页面坐标slider_center = slider_left + slider_size['width'] * self.device_pixel_ratio / 2  # 滑块中心页面坐标move_distance = gap_left_page - slider_left  # 需要滑动的距离print(f"gap_left (in image): {gap_left}")print(f"gap_center (in image): {gap_center}")print(f"captcha_left (page): {captcha_left}")print(f"gap_left_page: {gap_left_page}")print(f"slider_left: {slider_left}")print(f"slider_center: {slider_center}")print(f"move_distance (left edge align): {move_distance}")img1_debug = image1.copy()  # 调试用图片img2_debug = image2.copy()self.draw_debug_line(img1_debug, gap_left, 'green', 'beforecode_debug.png')  # 画缺口左边缘self.draw_debug_line(img1_debug, gap_center, 'red', 'beforecode_debug.png')  # 画缺口中心self.draw_debug_line(img2_debug, gap_left, 'green', 'aftercode_debug.png')self.draw_debug_line(img2_debug, gap_center, 'red', 'aftercode_debug.png')slider_center_in_img = int(slider_center - captcha_left)  # 滑块中心在图片内的横坐标self.draw_debug_line(img1_debug, slider_center_in_img, 'blue', 'beforecode_debug.png')  # 画滑块中心track = self.get_track(move_distance)  # 生成轨迹track.extend([3, -2, 1, -1])  # 加入回弹print(f"track: {track}")print(f"track sum: {sum(track)}")self.move_to_gap(slider, track)  # 拖动滑块time.sleep(2)  # 等待验证结果self.browser.close()  # 关闭浏览器

实现思路与设计原因:

        - 主流程串联所有步骤,自动化完成验证码识别与破解。

        - 关键变量和调试图片便于排查问题和优化算法。

        - 结构清晰,便于扩展和维护。

结语

        滑动验证码的自动识别与破解,是自动化测试、数据采集和安全攻防领域的经典难题。本文以实际工程代码为主线,系统梳理了滑动验证码的原理、反爬机制、识别与破解流程、核心算法实现、调试技巧与工程经验。通过对缺口识别、轨迹生成、滑块模拟等关键环节的逐步剖析,我们不仅掌握了破解滑动验证码的技术细节,也深入理解了背后的安全逻辑与攻防博弈。

        在实际工程中,滑动验证码的样式和反爬机制会不断演化,破解方法也需灵活调整。面对更复杂的验证码(如canvas绘制、AI行为识别、图片加密等),我们可以结合深度学习、图像处理、浏览器指纹伪装等多种手段,不断提升自动化能力。

        滑动验证码的研究,不仅有助于提升自动化测试和数据采集的效率,更有助于理解Web安全、反爬机制和人机交互的前沿发展。希望本章内容能为你的工程实践和技术探索提供有力参考。未来,随着AI与安全技术的持续进步,滑动验证码的攻防也将更加精彩,期待你在实践中不断创新、持续精进!

看到这里了还不给博主点一个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
再次感谢大家的支持!
你们的点赞就是博主更新最大的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NSSCTF-[NISACTF 2022]huaji?

下载附件得到文件 放到kali里面看看 发现是一张图片 用binwalk命令对其进行分离 发现需要密码 用010打开图片进行查看 对其进行解密 分别得到 ctf_NISA_2022 nisa_2022 发现ctf_NISA_2022是密码 得到flag NSSCTF{Nls_FumYEnnOjy}

nt!CcGetVacbMiss函数分析之设置好nt!_VACB然后调用函数nt!SetVacb

第一部分&#xff1a;MmMapViewInSystemCache函数返回 Status MmMapViewInSystemCache (SharedCacheMap->Section, &Vacb->BaseAddress, &NormalOffset, …

Uniapp+UView+Uni-star打包小程序极简方案

一、减少主包体积 主包污染源&#xff08;全局文件依赖&#xff09;劲量独立导入 componentsstaticmain.jsApp.vueuni.css 分包配置缺陷&#xff0c;未配置manifest.json中mp-weixin节点 "usingComponents" : true,"lazyCodeLoading" : "requiredC…

Teigha应用——解析CAD文件(DWG格式)Teigha在CAD C#二次开发中的基本应用

Teigha是一款专为开发者设计的工具&#xff0c;其核心技术在于强大的API和丰富的功能集&#xff0c;提供了一系列工具和方法&#xff0c;使开发者能够轻松地读取、解析和操作DWG文件。它支持多种操作系统&#xff0c;能在处理大型DWG文件时保持高效性能&#xff0c;还可用于构建…

JavaWeb:SpringBoot Bean管理

获取Bean Bean作用域 解决循环依赖方式 1.粗暴删除依赖 2.打破依赖配置 3.使用lazy注解 引入第三方Bean

Lua 脚本在 Redis 中的运用-23(Lua 脚本语法教程)

在 Redis 中编写和执行 Lua 脚本 Lua 脚本是在 Redis 中执行自定义逻辑的强大功能&#xff0c;可以直接在 Redis 服务器上执行。这减少了延迟&#xff0c;提高了性能&#xff0c;并能够实现客户端脚本难以或不可能实现的原子操作。通过在 Redis 中嵌入 Lua 脚本&#xff0c;您…

从零实现本地语音识别(FunASR)

FunASR 是达摩院开源的综合性语音处理工具包&#xff0c;提供语音识别&#xff08;ASR&#xff09;、语音活动检测&#xff08;VAD&#xff09;、标点恢复&#xff08;PUNC&#xff09;等全流程功能&#xff0c;支持多种主流模型&#xff08;如 Paraformer、Whisper、SenseVoic…

deepseek开源资料汇总

参考&#xff1a;DeepSeek“开源周”收官&#xff0c;连续五天到底都发布了什么? 目录 一、首日开源-FlashMLA 二、Day2 DeepEP 三、Day3 DeepGEMM 四、Day4 DualPipe & EPLB 五、Day5 3FS & Smallpond 总结 一、首日开源-FlashMLA 多头部潜在注意力机制&#x…

【C++ Qt】认识Qt、Qt 项目搭建流程(图文并茂、通俗易懂)

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 本章将开启Qt的学习&#xff0c;Qt是一个较为古老但仍然在GUI图形化界面设计中有着举足轻重的地位&#xff0c;因为它适合嵌入式和多种平台而被广泛使用…

AI应用 Markdown 渲染对比与原生实现方案

DeepSeek、豆包、腾讯元宝、ChatGPT 渲染实现对比表 产品解析方式渲染引擎/库UI 组件架构Markdown支持范围流程图/导图支持扩展架构及裁剪流式解析渲染DeepSeek原生解析&#xff08;非WebView&#xff09;采用 CommonMark 标准解析器&#xff08;推测使用 Markwon 库&#xff…

Ubuntu20.04系统安装,使用系统盘安装

1、系统安装 Ubuntu20.04系统安装&#xff0c;使用系统盘安装 查看ubuntu系统版本 lsb_release -a&#xff1a;显示发行版名称、版本号及代号 (base) rootai-System-Product-Name:/media/ai/wh/clash-for-linux-master# lsb_release -a No LSB modules are available. Distri…

(自用)Java学习-5.19(地址管理,三级联动,预支付)

1. 地址管理模块 地址展示 前端&#xff1a;通过 showAddress() 发起 Ajax GET 请求&#xff0c;动态渲染地址列表表格&#xff0c;使用 #{tag}、#{name} 等占位符替换真实数据。 后端&#xff1a; 控制器层调用 AddressService&#xff0c;通过 AddressMapper 查询用户地址数…

Spring 循环依赖:从原理到解决方案的全面解析

Spring 循环依赖&#xff1a;从原理到解决方案的全面解析 一、循环依赖的定义与分类 1. 什么是循环依赖&#xff1f; 在 Spring 框架中&#xff0c;循环依赖指的是多个 Bean 之间形成了依赖闭环。例如&#xff1a; Bean A 依赖 Bean BBean B 依赖 Bean CBean C 又依赖 Bean…

n 阶矩阵 A 可逆的充分必要条件是 ∣ A ∣ ≠ 0

n 阶矩阵 A 可逆的充分必要条件是 ∣ A ∣ ≠ 0 |A| \neq 0 ∣A∣0 的几何意义 1. 行列式的几何意义回顾 行列式 ∣ A ∣ |A| ∣A∣&#xff08;或 det ⁡ ( A ) \det(A) det(A)&#xff09;表示矩阵 A A A 所对应的线性变换对空间的体积缩放因子&#xff1a; ∣ A ∣ &…

Rockey Linux 安装ffmpeg

1.环境准备 Rockey linux 9.2 ffmpeg 静态资源包 这个是我自己的&#xff1a; https://download.csdn.net/download/liudongyang123/90920340https://download.csdn.net/download/liudongyang123/90920340 这个是官网的 Releases BtbN/FFmpeg-Builds GitHub 以上两个资…

wordcount在集群上的测试

1.将louts.txt文件从cg计算机复制到master节点上面&#xff0c;存放在/usr/local/hadoop 需要输入密码&#xff1a;83953588abc scp /root/IdeaProjects/mapReduceTest/lotus.txt root172.18.0.2:/usr/local/hadoop /WordCountTest/input 2.将lotus.txt文件从master这台机器…

AI+制造:中小企业的低成本智能化转型

文章内容过长&#xff0c;可以考虑直接跳转到文章末尾查看概要图 在制造业竞争日益激烈的今天&#xff0c;中小企业正面临着前所未有的挑战&#xff1a;人力成本持续攀升、能源消耗居高不下、质量控制难度增加。与此同时&#xff0c;数字化转型已成为行业共识&#xff0c;但高…

Linux C/C++编程 —— 线程技术总结

一、线程基本概念 线程是进程内的一个执行单元&#xff0c;多个线程共享进程的资源&#xff08;如内存、文件描述符等&#xff09;&#xff0c;但每个线程拥有自己的寄存器、栈等。与进程相比&#xff0c;线程的创建、切换开销较小&#xff0c;能更高效地利用 CPU 资源。 二、…

Femap许可证与网络安全策略

随着科技的快速发展&#xff0c;网络安全问题已成为各行各业关注的焦点。在电磁仿真领域&#xff0c;Femap作为一款领先的软件&#xff0c;其许可证的安全性和网络策略的重要性不言而喻。本文将探讨Femap许可证与网络安全策略的关系&#xff0c;确保您的电磁仿真工作能够在一个…

深度解析:SQLynx 如何筑牢数据库安全防线​

在数据驱动业务发展的时代&#xff0c;数据库作为企业核心资产的 “保险箱”&#xff0c;其安全性至关重要。一旦数据库遭遇攻击、数据泄露或被误操作&#xff0c;将给企业带来不可估量的损失。而 SQLynx 作为一款专注于数据库安全管理的工具&#xff0c;凭借其多项创新技术与功…