Selenium WebDriver XPath定位失效:Otodom房源爬取部分数据缺失求助
问题
爬取Otodom房源页面(https://www.otodom.pl/pl/oferta/idealna-inwestycja-super-komunikacja-ID4jIKa)时,部分数据能正常获取,但其余数据返回NaN。以下是我的代码及输出结果:
import time import pandas as pd from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait # 设置chromedriver路径 driver = webdriver.Chrome("chromedriver") # 房源页面地址 url = 'https://www.otodom.pl/pl/oferta/idealna-inwestycja-super-komunikacja-ID4jIKa' xpath_list = ['//*[@id="__next"]/main/div[3]/div[2]/header/div[2]/a', '//*[@id="__next"]/main/div[3]/div[2]/header/strong', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[1]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[2]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[3]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[4]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[5]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[6]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[7]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[8]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[2]/div/div[10]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/section[2]/div/div/div/p', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[1]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[2]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[3]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[4]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[5]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[6]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[7]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[8]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[9]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[10]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[11]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[12]/div[2]/div', '//*[@id="__next"]/main/div[3]/div[2]/div[8]/div[1]' ] Wartości = ["Adres", "Cena", "Powierzchnia", 'Forma własności', 'Liczba pokoi', 'Stan_wykończenia', 'Piętro','Balkon/Ogród/Taras', 'Czynsz', 'Miejsce parkingowe', 'Ogrzewanie','opis', 'Rynek', 'Typ ogłoszeniodawcy','Dostępne od','Rok zabudowy','Rodzaj zabudowy','Okna', 'Winda', 'Media','Zabezpieczenia','Wyposazenie','Informacje dodatkowe','Materiał budynku','Nr oferty'] # 打开房源页面 driver.get(url) time.sleep(5) accept_button = driver.find_element(By.ID, "onetrust-accept-btn-handler") accept_button.click() xpath_dict = {} for index, xpath in enumerate(xpath_list): try: # 通过XPath查找元素 element = driver.find_element(By.XPATH, xpath) # 将元素文本存入字典 xpath_dict[Wartości[index]] = element.text except: # 异常时存入NaN xpath_dict[Wartości[index]] = "NaN" pass
输出结果:
{'Adres': 'Warszawa, Białołęka, ul. Talarowa', 'Cena': '357 750 zł', 'Powierzchnia': '28,62 m²', 'Forma własności': 'pełna własność', 'Liczba pokoi': '1', 'Stan_wykończenia': 'do zamieszkania', 'Piętro': '2/4', 'Balkon/Ogród/Taras': 'balkon', 'Czynsz': 'NaN', 'Miejsce parkingowe': 'NaN', 'Ogrzewanie': 'miejskie', 'opis': 'Zapraszam do zakupu mieszkania na zasadach praw cesji.\nMieszkanie znajduje się na warszawskim Tarchominie, gdzie znajdziemy wszystkie potrzebne do życia usługi od sklepów po szkoły.Blisko osiedla komunikacja miejska ( autobusy,tramwaje) którą szybko dojedziemy do metra i innych ważnych punktów na mapie Warszawy.\nOsiedle składa się z dwóch budynków o niskiej zabudowie, a pomiędzy nimi dużo zieleni czy stojaki na rowery.\nNa dachach budynków zainstalowane panele fotowoltaiczne które zmniejszą opłaty za oświetlenie części wspólnych.\nJest możliwość do kupienia miejsca w garażu w budynku obok.\nWizualizacje wnętrz przedstawiają możliwe wykończenie wnętrza przez firmę specjalizującą się w tym zakresie.', 'Rynek': 'NaN', 'Typ ogłoszeniodawcy': 'NaN', 'Dostępne od': 'NaN', 'Rok zabudowy': 'NaN', 'Rodzaj zabudowy': 'NaN', 'Okna': 'NaN', 'Winda': 'NaN', 'Media': 'NaN', 'Zabezpieczenia': 'NaN', 'Wyposazenie': 'NaN', 'Informacje dodatkowe': 'NaN', 'Materiał budynku': 'NaN', 'Nr oferty': 'Nr oferty w Otodom: 63805574'}
问题定位与解决建议
问题原因
- 绝对XPath依赖页面结构:使用的是基于元素层级的绝对XPath,一旦页面DOM结构微调(比如新增/删除div、调整元素顺序),这些XPath就会失效。很多返回
NaN的字段,对应的XPath可能根本不存在于当前页面。 - 等待机制不可靠:
time.sleep(5)是固定等待,无法保证页面完全加载完成,若元素加载延迟,就会出现找不到的情况。 - 异常处理过于宽泛:捕获所有异常但不输出错误信息,无法区分是元素不存在还是加载失败,不利于排查问题。
- 部分字段可能不存在:部分房源本身没有某些信息(比如
Czynsz),页面不会渲染该字段,自然无法爬取到。
解决方法
1. 使用相对XPath替代绝对路径
基于元素的文本、class等属性定位,避免依赖层级结构。比如查找Rynek字段:
# 原绝对XPath://*[@id="__next"]/main/div[3]/div[2]/div[4]/div/div[1]/div[2]/div # 替换为相对XPath:通过标签文本定位键,再取相邻的数值元素 '//div[text()="Rynek"]/following-sibling::div'
这种方式即使页面结构变化,只要字段名称不变,就能正常定位。
2. 改用显式等待
替换time.sleep为WebDriverWait,等待元素加载完成:
from selenium.webdriver.support import expected_conditions as EC wait = WebDriverWait(driver, 10) # 最长等待10秒 # 在循环中替换原查找逻辑 element = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
3. 细化异常处理
捕获具体异常并打印错误信息,方便排查:
from selenium.common.exceptions import NoSuchElementException try: element = wait.until(EC.presence_of_element_located((By.XPATH, xpath))) xpath_dict[Wartości[index]] = element.text except NoSuchElementException: print(f"字段 {Wartości[index]} 未找到,对应XPath:{xpath}") xpath_dict[Wartości[index]] = "NaN"
4. 处理动态加载内容
部分字段可能需要滚动到可见区域才会加载,可添加滚动逻辑:
element = wait.until(EC.presence_of_element_located((By.XPATH, xpath))) driver.execute_script("arguments[0].scrollIntoView(true);", element) xpath_dict[Wartości[index]] = element.text
5. 验证字段是否存在
先检查页面是否有该字段的标签,再获取数值。比如判断Rynek是否存在:
try: label = wait.until(EC.presence_of_element_located((By.XPATH, '//div[text()="Rynek"]'))) value = label.find_element(By.XPATH, './following-sibling::div').text xpath_dict["Rynek"] = value except NoSuchElementException: xpath_dict["Rynek"] = "NaN"
内容的提问来源于stack exchange,提问作者Luki
相关产品推荐
相关产品推荐

