Python/Selenium:类实例化或定位器问题致元素查找失败?
问题根源与修复方案
核心错误:WebDriverWait 参数传递错误
你在BookingFilters类的wait_for_clickable方法里犯了关键错误:WebDriverWait的第一个参数必须传入Selenium的driver实例,而非BookingFilters类自身。
在Booking类中,因为它继承了webdriver.Chrome,self本身就是driver实例,所以WebDriverWait(self, ...)调用正确;但BookingFilters类的self是类实例,不是driver,必须用self.driver传入WebDriverWait才有效。
其他次要问题
- 导入缺失:
BookingFilters.py未导入WebDriver、WebDriverWait、EC等必要模块,运行时会报错。 - 定位器类型不匹配:
//div[text()="2 stars"]是XPATH表达式,你在Booking类的测试代码里错误使用了By.CSS_SELECTOR,需对应By.XPATH。 - 定位器语法错误:
div[data-filters-item*="class]的引号未闭合,正确写法是div[data-filters-item*="class"]。
修复后的代码
修改后的 BookingFilters.py
from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By class BookingFilters: def __init__(self, driver: WebDriver): self.driver = driver def apply_star_rating(self): star_filter_area = self.wait_for_clickable((By.CSS_SELECTOR, 'div[data-filters-group="class"]')) # 修正定位器类型为XPATH star_filter_selection = self.wait_for_clickable((By.XPATH, '//div[text()="2 stars"]')) print(star_filter_selection) if star_filter_area is not None: # 修正引号闭合问题 star_box = star_filter_area.find_elements(By.CSS_SELECTOR, 'div[data-filters-item*="class"]') for element in star_box: html = element.get_attribute('outerHTML') print(html) def wait_for_clickable(self, locator, timeout=1, poll_frequency=0.05): try: print(f'Trying to find element with {locator}') # 关键修复:传入self.driver而非self element_found = WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll_frequency) \ .until(EC.element_to_be_clickable(locator)) element_html = element_found.get_attribute('outerHTML') if element_found: print(f'Element found: {element_html}\n') return element_found except: print(f'============ element with {locator} Not Found ============\n') return None
修正Booking.py中的定位器类型错误
在apply_filters方法的测试代码中,把:
star_filter_selection = self.wait_for_clickable((By.CSS_SELECTOR, '//div[text()="2 stars"]'))
改为:
star_filter_selection = self.wait_for_clickable((By.XPATH, '//div[text()="2 stars"]'))
关于类封装思路的合理性
你的封装思路完全没问题,把筛选逻辑抽离到单独的BookingFilters类符合单一职责原则,能让代码更清晰易维护,问题只是实现时的参数传递错误,和思路无关。
额外优化建议
- 抽取公共基类:将
wait_for_clickable这类通用等待方法抽离到基类中,让Booking和BookingFilters继承,避免重复代码。 - 延长等待时长:当前1秒的timeout太短,容易因页面加载慢导致查找失败,可延长至5-10秒。
- 明确捕获异常:避免空except语句,建议捕获
TimeoutException等Selenium特定异常,方便调试。
内容的提问来源于stack exchange,提问作者ZackM
相关产品推荐
相关产品推荐

