Python使用Selenium如何滑动伪装为input[type=text]的区间滑块?

问题场景
爬取动态网站数据时,需要将图示区间滑块拖动到指定数值范围。经排查该滑块是被设置了display:none属性、伪装为input[type='text']的元素,滑动完成后关联文本框会自动按照{minValue}:{maxValue}的格式填充对应取值。
滑块对应的HTML结构如下:
<div class="slider slider-horizontal" id="" style="width: 100%;"><div class="slider-track"><div class="slider-track-low" style="left: 0px; width: 0%;"></div><div class="slider-selection" style="left: 0%; width: 100%;"></div><div class="slider-track-high" style="right: 0px; width: 0%;"></div></div><div class="tooltip tooltip-main top in" role="presentation" style="left: 50%; margin-left: -39.5px;"><div class="tooltip-arrow"></div><div class="tooltip-inner">2006 : 2022</div></div><div class="tooltip tooltip-min top" role="presentation" style="left: 0%; margin-left: 0px; display: none;"><div class="tooltip-arrow"></div><div class="tooltip-inner">2006</div></div><div class="tooltip tooltip-max top" role="presentation" style="left: 100%; margin-left: 0px; display: none;"><div class="tooltip-arrow"></div><div class="tooltip-inner">2022</div></div><div class="slider-handle min-slider-handle round" role="slider" aria-valuemin="2006" aria-valuemax="2022" aria-valuenow="2006" tabindex="0" style="left: 0%;"></div><div class="slider-handle max-slider-handle round" role="slider" aria-valuemin="2006" aria-valuemax="2022" aria-valuenow="2022" tabindex="0" style="left: 100%;"></div></div>
已验证无效的方案
之前尝试的操作均无法触发滑块真实状态更新,因为应用按钮读取的是滑块组件的内部状态和手柄实际位置,而非DOM属性或输入框值:
- 修改隐藏input的
display属性为block后,直接向文本框填入目标取值 - 执行JS脚本修改滑块手柄的
aria-valuenow属性 - 直接修改隐藏文本框的
value属性
对应尝试的代码如下:
driver.execute_script( 'document.getElementsByClassName("min-slider-handle")[0].setAttribute("aria-valuenow", 2019);' )
hidden_element = driver.find_element(By.CSS_SELECTOR, "#ID .slider-input") hidden_element[0].send_keys(f'{from_year}, {to_year}')
正确实现方案
该滑块是bootstrap-slider组件,提供两种可落地的实现方式:
方案1:Selenium模拟真实拖拽(通用兼容方案)
根据滑块总宽度、取值区间计算目标位置对应的水平偏移量,通过ActionChains模拟鼠标拖拽动作,和人工操作逻辑完全一致:
from selenium.webdriver.common.action_chains import ActionChains import time # 定位核心元素 slider_track = driver.find_element(By.CSS_SELECTOR, ".slider.slider-horizontal .slider-track") min_handle = driver.find_element(By.CSS_SELECTOR, ".min-slider-handle") max_handle = driver.find_element(By.CSS_SELECTOR, ".max-slider-handle") # 读取滑块基础参数 slider_width = slider_track.size["width"] min_val = int(min_handle.get_attribute("aria-valuemin")) max_val = int(min_handle.get_attribute("aria-valuemax")) total_range = max_val - min_val # 替换为需要设置的目标区间 target_min = 2019 target_max = 2021 # 计算拖动偏移量 min_offset = (target_min - min_val) / total_range * slider_width # 最大手柄默认在滑块最右端,偏移量为相对于当前位置的差值 max_offset = (target_max - min_val) / total_range * slider_width - slider_width # 先拖最小手柄再拖最大手柄,避免手柄交叉导致取值错误 ActionChains(driver).drag_and_drop_by_offset(min_handle, min_offset, 0).perform() time.sleep(0.2) ActionChains(driver).drag_and_drop_by_offset(max_handle, max_offset, 0).perform()
方案2:调用组件内置方法(无误差最优方案)
bootstrap-slider的实例会绑定在原始input元素上,直接调用实例的setValue方法会自动更新手柄位置、提示文本、输入框值,同时触发所有绑定的变更事件,不需要计算偏移,不受页面缩放、滑块尺寸变化影响:
# 定位被隐藏的原始绑定input slider_input = driver.find_element(By.CSS_SELECTOR, ".slider-input") # 传入目标区间,第二个参数设为true触发值变更事件 driver.execute_script(""" const sliderIns = arguments[0].slider; sliderIns.setValue([arguments[1], arguments[2]], true); """, slider_input, target_min, target_max)
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

