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

