You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Selenium处理限6次尝试的拼图验证码?

解决极验拼图验证码的6次分段移动问题

你当前的代码存在两个核心问题:

  1. 每次循环都重新点击并释放滑块,相当于多次独立滑动操作,会快速耗尽6次尝试机会
  2. 移动的是绝对偏移量(每次从起点移到固定x位置),而非分段的相对偏移,完全没利用6次尝试的限制逻辑

核心思路

要在6次内完成验证,必须先计算滑块需要移动的总距离,再将总距离拆分为6段逐步调整(或直接模拟人类滑动轨迹一次完成,避免浪费尝试次数)。

步骤1:计算滑块总移动距离

极验拼图的缺口位置可通过对比「完整背景图」和「带缺口背景图」的像素差异获取(需安装Pillow库):

from PIL import Image
import numpy as np
import base64
from io import BytesIO

def get_gap_distance(driver):
    # 定位验证码的两个canvas元素(需根据页面实际结构调整选择器)
    canvas_full = driver.find_element(By.CSS_SELECTOR, 'canvas.geetest_canvas_fullbg')
    canvas_slice = driver.find_element(By.CSS_SELECTOR, 'canvas.geetest_canvas_bg')
    
    # 将canvas转换为Image对象
    def canvas_to_img(canvas):
        img_base64 = driver.execute_script("return arguments[0].toDataURL('image/png').substring(21);", canvas)
        img_bytes = base64.b64decode(img_base64)
        return Image.open(BytesIO(img_bytes))
    
    img_full = canvas_to_img(canvas_full)
    img_slice = canvas_to_img(canvas_slice)
    
    # 对比像素差异,定位缺口x坐标
    diff = np.abs(np.array(img_full) - np.array(img_slice)).sum(axis=2)
    gap_x = np.argmax(diff.mean(axis=0))
    
    # 计算滑块初始位置与缺口的差值(补偿滑块自身宽度误差)
    slider = driver.find_element(By.CLASS_NAME, 'geetest_slider_button')
    slider_x = slider.location['x']
    return gap_x - slider_x - 10

步骤2:按6段拆分移动滑块

如果必须严格分6次移动,可按以下方式实现(保持滑块按住状态,分段相对移动):

import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By

try:
    slider = driver.find_element(By.CLASS_NAME, 'geetest_slider_button')
    total_distance = get_gap_distance(driver)
    if total_distance <= 0:
        print("无需移动滑块")
        pass
    
    step = total_distance / 6
    actions = ActionChains(driver)
    
    # 按住滑块开始移动
    actions.click_and_hold(slider).perform()
    time.sleep(0.1)
    
    # 分6次完成分段移动
    for _ in range(6):
        actions.move_by_offset(step, 0).perform()
        time.sleep(0.05)  # 模拟人类移动的微小停顿
    
    actions.release().perform()
    time.sleep(1)
    
except Exception as e:
    print(f'滑块处理出错: {str(e)}')

更优方案:一次模拟人类滑动轨迹

其实没必要分6次尝试,模拟人类先快后慢的滑动轨迹,一次就能完成验证,避免触发封禁逻辑:

def human_like_slide(actions, total_distance):
    # 快速移动80%距离
    actions.move_by_offset(total_distance * 0.8, 0).perform()
    time.sleep(0.08)
    # 减速移动15%距离
    actions.move_by_offset(total_distance * 0.15, 0).perform()
    time.sleep(0.1)
    # 最后微调剩余5%距离
    actions.move_by_offset(total_distance * 0.05, 0).perform()
    time.sleep(0.05)

try:
    slider = driver.find_element(By.CLASS_NAME, 'geetest_slider_button')
    total_distance = get_gap_distance(driver)
    if total_distance <= 0:
        pass
    
    actions = ActionChains(driver)
    actions.click_and_hold(slider).perform()
    human_like_slide(actions, total_distance)
    actions.release().perform()
    time.sleep(1)
except Exception as e:
    print(f'滑块处理出错: {str(e)}')

注意事项

  • 极验的canvas元素选择器可能随网站更新变化,需根据实际页面结构调整
  • 图片对比时要确保页面无缩放,避免坐标偏差
  • 即使通过验证码,短时间大量请求仍会触发封禁,需控制请求频率

内容的提问来源于stack exchange,提问作者SolidOpt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 01:55:08