基于Selenium与图鉴API的滑动验证码自动化破解实战

📅 发布时间:2026/7/6 1:08:44 👁️ 浏览次数:
基于Selenium与图鉴API的滑动验证码自动化破解实战
1. 为什么我们需要搞定滑动验证码做爬虫的朋友十有八九都跟验证码“斗智斗勇”过。尤其是那种需要你用手指按住滑块拖到缺口位置的滑动验证码它不像传统字符验证码那样随便找个OCR库就能识别。它考验的是你的“模拟人手操作”的能力。我刚开始做自动化的时候一看到这种滑块就头疼手动操作吧效率太低想用程序模拟吧轨迹太假分分钟被识别出来是机器。后来我发现核心难点其实就两个第一缺口位置怎么找第二怎么模仿人的滑动轨迹自己写图像识别算法去算缺口位置不是不行但太费劲了要处理背景干扰、阴影、抗锯齿还得应对图片的各种随机变换。对于大多数以业务为导向的开发者来说这投入产出比太低了。这时候第三方打码平台的价值就凸显出来了。比如我们这次要用的图鉴它本质上是一个提供图像识别能力的API服务。你把验证码图片传给它它告诉你缺口的位置坐标你只需要专注于用Selenium去模拟滑动这个动作就行。这就好比你要组装一台电脑你不用自己去造CPU和显卡直接从市场上买来成熟的配件然后组装起来效率高稳定性也好。所以这套“Selenium 图鉴API”的组合拳就成了破解滑动验证码的一个非常实用且高效的方案。它特别适合那些需要处理登录、注册等带有滑动验证环节的爬虫项目。接下来我就带你从零开始手把手走一遍这个实战流程把我踩过的坑和总结的经验都分享给你。2. 实战前的准备工作工具与账号工欲善其事必先利其器。在开始写代码之前我们得先把“家伙事儿”备齐。2.1 Selenium环境搭建Selenium是我们模拟浏览器操作的核心工具。首先用pip安装它pip install selenium光有Selenium还不够你还需要一个浏览器驱动。最常用的是ChromeDriver它需要和你电脑上安装的Chrome浏览器版本对应。你可以去ChromeDriver官网下载或者更简单点用webdriver-manager这个库自动管理。安装webdriver-managerpip install webdriver-manager然后在代码里这样初始化浏览器就不用操心驱动版本了from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice) driver.get(https://www.example.com)实测下来用webdriver-manager非常稳省去了手动下载和配置环境变量的麻烦特别适合新手。2.2 图鉴平台注册与配置接下来是“外脑”——图鉴平台。我们打开图鉴的官网这里用www.ttshitu.com举例注册一个账号。注册过程很简单跟普通网站没区别。注册成功后你需要进行充值。图鉴的计费方式是按识别次数扣费通常一次滑动验证码识别只需要几分钱。对于学习和测试来说充个几块钱就完全够用了。充值时平台会给你一个“提分”这个“提分”就是你的账户余额每次调用API都会从这里扣费。充值完成后在后台你主要需要记住两个东西用户名username和密码password。这两个参数在调用API时会用到。另外你还需要知道不同验证码类型对应的typeid。比如普通的滑块缺口识别typeid可能是33具体以图鉴官网文档为准。这一步千万别搞错类型选错了识别结果肯定不对。3. 核心原理拆解从图片到滑动距离环境准备好了我们得先搞清楚我们要做什么。整个过程可以分解为以下几个关键步骤我画个简单的流程图帮你理解触发验证码通过Selenium点击登录按钮让网页弹出滑动验证码组件。获取验证码图片这是最关键也最易出错的一步。我们需要从网页复杂的DOM结构里找到背景图带缺口的完整图和滑块图那个可移动的小块的图片地址并把它们下载到本地。很多时候这些图片是以CSS背景图background-image或者img标签的src属性形式存在甚至可能是经过Base64编码直接嵌入在HTML里的。你需要用Selenium定位到对应的元素然后提取出图片的URL或Base64数据。调用图鉴API识别缺口位置将下载下来的背景图注意通常是背景图传给图鉴API。API会返回一个结果这个结果通常是缺口左上角在背景图中的X坐标。计算滑块需要滑动的距离注意API返回的坐标是相对于背景大图的。但我们的滑块是在一个更小的滑块轨道上移动而且滑块初始位置通常不是从0开始。所以需要一个换算。比如原背景图宽670像素缺口距离背景图左侧398像素而滑块轨道的可视区域可能只有340像素宽。那么滑块在轨道上需要移动的距离X (398 / 670) * 340。这利用了相似图形的比例性质。模拟人类滑动轨迹这是另一个核心。你不能简单地把滑块瞬间移动到计算出的距离。那样太“机器”了高级的反爬机制能轻易检测出来。我们需要用Selenium的ActionChains动作链来模拟人的操作先点击并按住滑块然后以变速的方式移动鼠标最后释放。轨迹最好包含先加速、再匀速、最后减速微调的过程。处理验证结果与异常滑动完成后页面会验证。如果失败我们需要能够捕获到这个失败然后点击刷新按钮重新获取验证码再来一遍。这个过程通常需要放在一个循环里直到成功登录或达到重试上限。4. 代码实战一步步实现自动化登录理论说再多不如一行代码。我们找一个有滑动验证码的网站比如案例中的欧模网来实际操练一下。我会把代码拆开一步步解释。4.1 图片获取与预处理首先我们启动浏览器打开登录页并输入账号密码触发验证码。from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time # 初始化浏览器 driver webdriver.Chrome() driver.get(https://www.om.cn/login) driver.maximize_window() # 最大化窗口确保元素位置稳定 # 切换到邮箱登录方式根据实际网站结构操作 # 这里需要你根据目标网站的实际情况用开发者工具查看元素找到正确的定位方式 # 例如 # driver.find_element(By.XPATH, //span[text()邮箱登录]).click() # 输入邮箱和密码 # email_input driver.find_element(By.NAME, email) # email_input.send_keys(your_emailexample.com) # password_input driver.find_element(By.NAME, password) # password_input.send_keys(your_password) # 点击登录按钮触发验证码 # login_button driver.find_element(By.XPATH, //button[typesubmit]) # login_button.click() # time.sleep(2) # 等待验证码加载触发验证码后最难的部分来了获取图片。滑动验证码的图片通常在一个iframe里面所以第一步是切换进去。# 切换到验证码的iframe框架这个iframe的id或name需要你通过开发者工具查看 iframe driver.find_element(By.ID, tcaptcha_iframe_dy) driver.switch_to.frame(iframe) # 定位背景图元素 bg_element driver.find_element(By.ID, slideBg) # 获取背景图的URL它可能藏在style属性的background-image里 bg_style bg_element.get_attribute(style) # 通常格式是background-image: url(https://xxx.com/xxx.jpg); import re bg_url_match re.search(rurl\((.?)\), bg_style) if bg_url_match: bg_url bg_url_match.group(1) # 有时URL可能是相对路径需要拼接 if bg_url.startswith(//): bg_url https: bg_url elif not bg_url.startswith(http): # 可能需要拼接基础URL bg_url https://t.captcha.qq.com bg_url # 以案例网站为例拿到图片URL后我们用requests库把它下载下来保存为本地文件供图鉴API读取。import requests bg_response requests.get(bg_url) with open(background.png, wb) as f: f.write(bg_response.content)4.2 调用图鉴API获取缺口位置现在我们有了背景图background.png。接下来编写调用图鉴API的函数。import base64 import json def recognize_gap(image_path, username, password, typeid33): 调用图鉴API识别图片缺口位置 :param image_path: 背景图片的本地路径 :param username: 图鉴用户名 :param password: 图鉴密码 :param typeid: 验证码类型ID滑动缺口识别一般为33 :return: 缺口左上角的x坐标整数 with open(image_path, rb) as f: img_bytes f.read() b64_data base64.b64encode(img_bytes).decode(utf-8) data { username: username, password: password, typeid: typeid, image: b64_data } api_url http://api.ttshitu.com/predict try: response requests.post(api_url, jsondata) result response.json() if result[success]: # 返回的坐标可能是一个字符串如 245 return int(float(result[data][result])) else: print(f识别失败: {result[message]}) return None except Exception as e: print(fAPI请求异常: {e}) return None # 使用示例 gap_x recognize_gap(background.png, 你的图鉴用户名, 你的图鉴密码) if gap_x: print(f识别到的缺口X坐标: {gap_x})这里有几个坑我踩过一是图片要转换成Base64格式二是typeid一定要选对三是API返回的坐标可能是字符串需要转换成数值。4.3 距离换算与轨迹模拟拿到缺口在背景图中的坐标gap_x后我们要把它换算成滑块在浏览器中实际需要滑动的像素距离。 假设我们通过测量或分析得知背景原图宽度bg_width 670网页上滑块轨道可视区域宽度track_width 340滑块初始位置可能有一个偏移比如滑块本身有宽度或者起点不在0处假设为offset 30那么滑块需要滑动的距离distance计算公式为distance (gap_x / bg_width) * track_width - offset这个offset很关键因为滑块本身有宽度你滑动的起始点是滑块的中间或左侧而不是轨道的绝对零点。这个值需要你根据实际网页的CSS样式去测量和调整可能需要反复试验几次。bg_width 670 # 背景图实际宽度 track_width 340 # 网页上滑轨的宽度 offset 30 # 初始偏移量需要根据实际情况调整 slide_distance (gap_x / bg_width) * track_width - offset print(f计算出的滑动距离: {slide_distance})接下来是最体现“人性化”的一步——模拟滑动。我们使用Selenium的ActionChains。from selenium.webdriver.common.action_chains import ActionChains # 定位滑块元素 slider driver.find_element(By.ID, tcaptcha_drag_thumb) # 根据实际情况修改定位方式 action ActionChains(driver) action.click_and_hold(slider).perform() # 按住滑块不放 # 模拟人的滑动轨迹先快后慢加入随机抖动 import random total_distance slide_distance current_x 0 move_steps [] # 记录每一步移动的距离 # 生成一个非匀速的移动序列例如前30%加速中间40%匀速后30%减速 accelerate_steps int(total_distance * 0.3) uniform_steps int(total_distance * 0.4) decelerate_steps total_distance - accelerate_steps - uniform_steps # 生成加速阶段的步长逐渐增大 for i in range(accelerate_steps): step random.uniform(1, 3) # 加速阶段步长较大 move_steps.append(step) # 生成匀速阶段的步长 for i in range(uniform_steps): step random.uniform(2, 3) move_steps.append(step) # 生成减速阶段的步长逐渐减小 for i in range(decelerate_steps): step random.uniform(0.5, 2) move_steps.append(step) # 为了防止最后差一点确保总步长和等于目标距离 sum_steps sum(move_steps) move_steps [x / sum_steps * total_distance for x in move_steps] # 执行滑动 for step in move_steps: action.move_by_offset(step, random.uniform(-1, 1)).perform() # 加入微小的Y轴抖动更像人 time.sleep(random.uniform(0.02, 0.1)) # 每步之间随机停顿 # 滑动到位后稍微停顿一下模拟人的犹豫 time.sleep(0.3) # 最后可能还需要一个微小的回拉或确认动作这取决于具体网站 # action.move_by_offset(-2, 0).perform() # time.sleep(0.1) # 释放滑块 action.release().perform()这段轨迹模拟代码是破解滑动验证码的灵魂。直接move_by_offset(slide_distance, 0)是必被检测的。加入了变速、随机停顿和Y轴抖动后成功率会大大提升。4.4 异常处理与重试机制滑动完成后页面会进行验证。我们需要判断是否成功。# 滑动完成后等待一小段时间让页面反应 time.sleep(2) # 判断是否还在验证码页面或者是否跳转到了登录成功页面 # 方法1检查iframe是否还存在验证成功通常会移除或隐藏iframe try: driver.switch_to.default_content() # 先切回主文档 # 尝试再次定位iframe如果找不到可能意味着成功了 driver.find_element(By.ID, tcaptcha_iframe_dy) still_in_captcha True except: still_in_captcha False # 方法2检查页面标题或某个成功登录后才出现的元素 if driver.title 欧模网-账户登录 or still_in_captcha: print(验证失败尝试刷新重试...) try: # 点击刷新按钮重新开始 driver.switch_to.frame(iframe) # 切回iframe refresh_btn driver.find_element(By.ID, reload) refresh_btn.click() time.sleep(1) # 等待新验证码加载 # 然后回到步骤2重新获取图片、识别、滑动... # 这里最好将整个过程封装成一个函数方便递归或循环调用 except Exception as e: print(f刷新失败: {e}) else: print(登录成功) # 进行后续操作...把上面的所有步骤整合起来封装成一个带循环重试的函数就是一个健壮的滑动验证码破解脚本了。我建议重试次数设置个3-5次避免无限循环。5. 避坑指南与高级技巧照着上面的步骤做大部分常见的滑动验证码都能搞定。但实际项目中你肯定会遇到更多“妖孽”。这里分享几个我踩过的坑和应对技巧。5.1 常见问题与排查图片下载失败或识别不准首先检查你是否正确切换到了iframe内部。很多验证码组件都是嵌套在iframe里的不在里面操作你根本找不到元素。其次检查图片URL是否正确有时URL是动态生成的带有时间戳或Token需要观察其规律。滑动距离总是差一点这多半是距离换算公式里的offset初始偏移量没算对。你需要用浏览器的开发者工具仔细测量滑块初始位置和轨道起点之间的像素差。也可能是因为网页对图片进行了缩放你需要获取元素的实际显示尺寸而不是图片的原始尺寸。轨迹被识别为机器你的滑动轨迹太“完美”了。务必加入变速、随机停顿和轻微抖动。可以多录几次自己手动滑动的鼠标轨迹分析其运动模式然后用程序去拟合。网上也有一些开源的人类行为轨迹生成库可以借鉴。图鉴API返回空或错误第一确认你的账户余额充足。第二确认typeid是否正确。第三检查你上传的图片格式和内容是否正确有时候下载的图片可能不是完整的背景图而是被切割过的。5.2 应对更复杂的验证码有些网站为了增加难度会使用动态模糊背景、滑块拼图非纯缺口而是需要旋转或拼合的图案、或者点选验证。对于这些动态背景图鉴等平台通常也有对应的识别类型。你需要截取多张不同状态的背景图或者找到生成动态效果的静态底图。滑块拼图识别难度更大需要API能返回更复杂的坐标信息比如旋转角度。图鉴平台也提供拼图识别服务但typeid不同调用前仔细阅读文档。点选验证这需要识别多个目标物并依次点击。思路类似截图 - 调用API获取多个坐标 - 用ActionChains依次点击。关键在于模拟点击时的间隔和顺序要随机化。5.3 关于封IP与行为检测频繁调用验证码识别和登录很容易触发网站的风控导致IP被封。这时候你需要考虑使用代理IP池让你的请求来自不同的IP地址。市面上有很多代理IP服务商。降低操作频率在操作之间增加随机的、长时间的等待模拟真人浏览。完善浏览器指纹高级反爬会检测浏览器环境。Selenium可以通过options添加一些参数来隐藏自动化特征但完全模拟一个真实浏览器很难。可以考虑使用undetected-chromedriver这类专门对抗检测的驱动。备用方案对于核心业务自动化登录只是手段之一。也可以考虑维护Cookie池或者寻找是否有其他无需验证码的接口。说到底自动化破解验证码是一场攻防战。我们的代码需要不断适应网站的变化。今天有效的方法明天可能就失效了。所以理解原理比复制代码更重要。当你掌握了“获取图片-识别坐标-模拟滑动”这个核心流程后无论验证码怎么变你都有思路去分析和解决。最后记得合理合法地使用这些技术遵守网站的robots.txt协议别给别人的服务器造成太大压力。