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

Booking.com可用日期抓取报错:StaleElementReferenceException求助

解决Booking.com日期抓取的StaleElementReferenceException问题

问题原因

  • 点击日期选择按钮后,日历组件的DOM会重新渲染,原代码中提前获取的元素列表会因DOM更新而失效,触发StaleElementReferenceException。
  • time.sleep(3)属于固定等待,无法精准匹配日历加载完成的时机,容易出现元素未就绪就抓取的情况。
  • 原代码中尝试获取calendar-day__price属性是错误的,这是元素的类名而非属性,判断日期可用状态需要检查元素的类(如calendar-day--available或calendar-day--blocked)。

修复后的代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.maximize_window()
wait = WebDriverWait(driver, 20)
test_url = 'https://www.booking.com/hotel/gr/diamandi-20.en-gb.html?label=gen173nr-1DCAEoggI46AdIM1gEaFyIAQGYAQm4ARjIAQzYAQPoAQGIAgGoAgS4ApGp7ZgGwAIB0gIkZTBjOTA2MTQtYTc0MC00YWUwLTk5ZWEtMWNiYzg3NThiNGQ12AIE4AIB&sid=47583bd8c0122ee70cdd7bb0b06b0944&aid=304142&ucfs=1&arphpl=1&checkin=2022-10-24&checkout=2022-10-30&dest_id=-829252&dest_type=city&group_adults=2&req_adults=2&no_rooms=1&group_children=0&req_children=0&hpos=2&hapos=2&sr_order=popularity&srpvid=f0f16af3449102aa&srepoch=1662736362&all_sr_blocks=852390201_352617405_2_0_0&highlighted_blocks=852390201_352617405_2_0_0&matching_block_id=852390201_352617405_2_0_0&sr_pri_blocks=852390201_352617405_2_0_0__30000&from=searchresults#hotelTmpl'
driver.get(test_url)

# 等待日期选择按钮可点击并点击
date_button = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'xp__dates__checkin')))
driver.execute_script('arguments[0].click()', date_button)

# 等待日历内容加载完成
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[@data-bui-ref="calendar-content"]')))

# 重新获取所有日期元素,避免stale引用
date_elements = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//div[@data-bui-ref="calendar-content"]//span[@aria-label]')))

date_list = []
availability_list = []

for elem in date_elements:
    # 获取日期文本
    date_text = elem.get_attribute("aria-label")
    date_list.append(date_text)
    
    # 判断可用状态:检查父元素是否包含blocked类
    parent_elem = elem.find_element(By.XPATH, './..')
    is_blocked = 'calendar-day--blocked' in parent_elem.get_attribute('class')
    availability_list.append('不可用' if is_blocked else '可用')

# 输出结果
for date, status in zip(date_list, availability_list):
    print(f"日期: {date}, 状态: {status}")

driver.quit()

关键修复点

  • 使用显式等待替代固定sleep:等待日期按钮可点击、日历内容可见,确保DOM完全渲染后再操作元素。
  • 日历加载完成后重新获取元素列表:避免因DOM更新导致的元素引用失效。
  • 修正状态判断逻辑:通过父元素的calendar-day--blocked类判断日期是否可用,替代原代码中错误的属性获取方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:01:07