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

如何用WebDriver读取Booking.com日历上用户选择的起止日期

需求说明

我正在学习网页抓取,需要让WebDriver等待用户在Booking.com的日历中手动选择开始日期和结束日期,之后读取这两个日期,用来处理该时间段内的可用房源,希望能得到帮助。


现有代码片段

获取日历日期的代码

tables = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//table[@role='grid']")))
table_first_month = tables[0].find_element(By.TAG_NAME, "tbody")
all_dates = table_first_month.find_elements(By.XPATH, "//td[@role='gridcell']")

for date in all_dates:
    date_span = date.find_element(By.TAG_NAME, "span")
    aria_label_span = date_span.get_attribute("aria-label")
    print(aria_label_span) 
    # userStartDate = wait.until(EC.element_to_be_clickable((this is where i need help)))
    if aria_label_span == str(userStartDate):
        date_span.click()
        time.sleep(4)
        break

日历翻页验证函数

def press_right_arrow_until_date_is_found(date):
    # get the text of the initial calendar
    current_calendar = driver.find_element(By.XPATH, "/html[1]/body[1]/div[2]/div[1]/div[3]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]/form[1]/div[1]/div[3]/div[4]/div[1]/div[1]").text
    # while the date does not appear in the calendar view press right arrow until it does
    while(date_formater(date) not in current_calendar):
        right_arrow = driver.find_element(By.XPATH,
            "//button[@class='fc63351294 a822bdf511 e3c025e003 fa565176a8 cfb238afa1 ae1678b153 c9fa5fc96d be298b15fa']")
        right_arrow.click()
        current_calendar = driver.find_element(By.XPATH,
            "/html[1]/body[1]/div[2]/div[1]/div[3]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]/form[1]/div[1]/div[3]/div[4]/div[1]/div[1]").text

解决方案

1. 等待用户手动选择日期

核心思路是监听用户选择后日历中出现的「选中状态日期元素」,通过WebDriverWait等待该元素出现后提取日期值:

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

# 初始化等待器(最多等待30秒,给用户足够选择时间)
wait = WebDriverWait(driver, 30)

# 等待用户选择开始日期(监听带有选中标记的日期单元格)
selected_start_elem = wait.until(
    EC.presence_of_element_located((By.XPATH, "//td[@role='gridcell' and contains(@class, 'selected')]"))
)
userStartDate = selected_start_elem.find_element(By.TAG_NAME, "span").get_attribute("aria-label")

# 等待用户选择结束日期(排除已选中的开始日期,确保拿到第二个选中的日期)
selected_end_elem = wait.until(
    EC.presence_of_element_located((By.XPATH, "//td[@role='gridcell' and contains(@class, 'selected') and not(preceding-sibling::td[contains(@class, 'selected')])]"))
)
userEndDate = selected_end_elem.find_element(By.TAG_NAME, "span").get_attribute("aria-label")

print(f"开始日期:{userStartDate}")
print(f"结束日期:{userEndDate}")

2. 修复现有代码的问题

  • 日期查找范围错误:原代码中table_first_month.find_elements(By.XPATH, "//td[@role='gridcell']")使用绝对XPath,会返回整个页面的所有日期单元格,应改为相对路径.//td[@role='gridcell'],仅查找当前月份表格内的日期:
    all_dates = table_first_month.find_elements(By.XPATH, ".//td[@role='gridcell']")
    
  • 绝对路径不稳定:原翻页函数使用绝对XPath,容易因页面结构变动失效,改用相对定位+属性定位优化:
    def press_right_arrow_until_date_is_found(date):
        # 定位日历容器(用更稳定的属性定位)
        calendar_container = driver.find_element(By.CSS_SELECTOR, "div[data-testid='calendar-month']")
        target_date_str = date_formater(date)
        
        while target_date_str not in calendar_container.text:
            # 用aria-label定位翻页按钮,比class更稳定
            right_arrow = driver.find_element(By.XPATH, "//button[@aria-label='Next month']")
            right_arrow.click()
            # 等待日历刷新完成
            wait.until(EC.staleness_of(calendar_container))
            calendar_container = driver.find_element(By.CSS_SELECTOR, "div[data-testid='calendar-month']")
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:54:27