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

Selenium遍历日期选择器选可用日期及预约时间解决方案

问题描述

我正在编写脚本,用Selenium操作日期选择器预约业务。可用日期显示为绿色,但无法通过class、title这类属性直接定位(不确定其出现时机)。选中可用日期后,会触发原本隐藏的预约时间和签证类型下拉列表。需解决两个核心问题:

  • 遍历所有日期,找到第一个可用日期并选中
  • 遍历预约时间,找到第一个可用时段并选中

当前已有部分代码:

from selenium.webdriver.common.by import By 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as ec 
import sys 

available_dates = driver.find_elements(By.XPATH, "//div[@class='datepicker-days']/table/tbody/tr/td[not(contains(@class, 'disabled'))]") 

for date in available_dates:
 print(date.text)

可用日期HTML示例:

<td class="day activeClass" title="Book">23</td>
解决方案

1. 定位并选中可用日期

由于可用日期出现时机不确定,必须用显式等待轮询加载,同时加入月份切换逻辑处理当前月无可用日期的情况:

# 等待日期选择器加载完成
datepicker = WebDriverWait(driver, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "datepicker-days"))
)

found_available_date = False
while not found_available_date:
    # 获取所有非禁用的日期,优先匹配带activeClass的元素
    available_dates = driver.find_elements(By.XPATH, "//div[@class='datepicker-days']/table/tbody/tr/td[not(contains(@class, 'disabled')) and contains(@class, 'day')]")
    
    if available_dates:
        # 优先选择标记为activeClass的可用日期
        for date in available_dates:
            if "activeClass" in date.get_attribute("class"):
                # 用JS点击避免元素不可交互问题
                driver.execute_script("arguments[0].click();", date)
                print(f"已选中可用日期: {date.text}")
                found_available_date = True
                break
        # 若无activeClass标记,选择第一个非禁用日期
        if not found_available_date:
            driver.execute_script("arguments[0].click();", available_dates[0])
            print(f"已选中可用日期: {available_dates[0].text}")
            found_available_date = True
    else:
        # 切换到下一月(需根据实际页面调整下一月按钮的定位器)
        try:
            next_month_btn = driver.find_element(By.XPATH, "//th[@class='next']")
            next_month_btn.click()
            # 等待月份切换完成
            WebDriverWait(driver, 5).until(ec.staleness_of(datepicker))
            datepicker = WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.CLASS_NAME, "datepicker-days")))
        except Exception:
            print("已无更多月份可切换,未找到可用日期")
            sys.exit(1)

2. 定位并选中可用预约时段

选中日期后,预约时间下拉列表会从隐藏变为可见,同样用显式等待确保元素加载完成:

try:
    # 等待预约时间下拉列表可见(替换为实际页面的元素定位器)
    time_dropdown = WebDriverWait(driver, 10).until(
        ec.visibility_of_element_located((By.XPATH, "//select[@id='appointment-time']"))
    )
    # 获取所有非禁用的时段选项
    available_times = time_dropdown.find_elements(By.XPATH, "./option[not(@disabled)]")
    
    if available_times:
        available_times[0].click()
        print(f"已选中可用时段: {available_times[0].text}")
    else:
        print("当前日期无可用预约时段")
        sys.exit(1)
except Exception as e:
    print(f"加载预约时段失败: {str(e)}")
    sys.exit(1)

完整整合代码

from selenium.webdriver.common.by import By 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as ec 
import sys 

# --- 处理日期选择器 ---
datepicker = WebDriverWait(driver, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "datepicker-days"))
)

found_date = False
while not found_date:
    available_dates = driver.find_elements(By.XPATH, "//div[@class='datepicker-days']/table/tbody/tr/td[not(contains(@class, 'disabled')) and contains(@class, 'day')]")
    if available_dates:
        for date in available_dates:
            if "activeClass" in date.get_attribute("class"):
                driver.execute_script("arguments[0].click();", date)
                print(f"已选中可用日期: {date.text}")
                found_date = True
                break
        if not found_date:
            driver.execute_script("arguments[0].click();", available_dates[0])
            print(f"已选中可用日期: {available_dates[0].text}")
            found_date = True
    else:
        try:
            next_month_btn = driver.find_element(By.XPATH, "//th[@class='next']")
            next_month_btn.click()
            WebDriverWait(driver, 5).until(ec.staleness_of(datepicker))
            datepicker = WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.CLASS_NAME, "datepicker-days")))
        except Exception:
            print("未找到可用日期,已无更多月份可切换")
            sys.exit(1)

# --- 处理预约时段选择 ---
try:
    time_dropdown = WebDriverWait(driver, 10).until(
        ec.visibility_of_element_located((By.XPATH, "//select[@name='appointment-time']"))
    )
    available_times = time_dropdown.find_elements(By.XPATH, "./option[not(@disabled)]")
    if available_times:
        available_times[0].click()
        print(f"已选中可用时段: {available_times[0].text}")
    else:
        print("当前日期无可用预约时段")
        sys.exit(1)
except Exception as e:
    print(f"预约时段加载失败: {str(e)}")
    sys.exit(1)

关键说明

  • 用WebDriverWait显式等待替代直接查找,彻底解决元素加载时机不确定的问题
  • 采用driver.execute_script点击日期,规避元素被遮挡、不可交互的常见问题
  • 加入月份切换逻辑,覆盖当前月无可用日期的场景
  • 优先匹配activeClass标记的日期,完全贴合提供的HTML结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:13:59