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
相关产品推荐
相关产品推荐

