使用Selenium XPath提取Kijiji电话号码时遇NoSuchElementException问题
问题:Kijiji电话号码提取时XPath控制台有效但代码抛出NoSuchElementException
我尝试从Kijiji的号码字段提取电话号码,在浏览器控制台输入XPath能识别并高亮对应字段,但运行Selenium代码时却抛出NoSuchElementException异常。
DOM结构说明
点击显示号码的按钮后,页面会生成带有phoneNumberContainer类的<a>标签,用于展示电话号码。
代码与报错说明
代码运行到定位电话号码元素的步骤时,抛出NoSuchElementException,提示无法找到目标元素。
尝试过的XPath
//a[contains(@class,'phoneNumberContainer')]//button[contains(@class,'phoneNumberContainer')]
目标URL
https://www.kijiji.ca/b-cars-trucks/edmonton/c174l1700203?adRemoved=4722799
完整代码
from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome("E:\\Selenium\\Driver\\chromedriver.exe") driver.get("https://www.kijiji.ca/b-cars-trucks/edmonton/c174l1700203?adRemoved=4722799") vehicleTitles = driver.find_elements(By.XPATH,"//a[contains(@class,'title')]") for title in vehicleTitles: print(title.text) driver.find_element(By.LINK_TEXT,title.text).click() driver.find_element(By.XPATH,"//button[contains(@class,'phoneNumberContainer')]").click() Number = driver.find_element(By.XPATH,"//a[contains(@class,'phoneNumberContainer')]") print(Number.text) driver.maximize_window()
解决方案
问题核心是页面加载延迟,Selenium执行速度快于元素渲染,同时代码存在页面切换的逻辑漏洞,以下是修复步骤:
- 添加显式等待
引入WebDriverWait等待元素状态,避免因加载速度慢导致的元素未找到:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC
- 修复页面切换逻辑
点击标题会打开新标签页,必须切换到新标签页才能操作内部元素:
# 记录原页面句柄 original_window = driver.current_window_handle # 点击标题打开新页面 title.click() # 等待新标签页加载并切换 WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) for window_handle in driver.window_handles: if window_handle != original_window: driver.switch_to.window(window_handle) break
- 等待元素可交互后再操作
等待显示号码的按钮可点击,再等待电话号码元素出现后提取:
# 等待显示号码按钮并点击 show_phone_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(@class,'phoneNumberContainer')]")) ) show_phone_btn.click() # 等待电话号码元素加载完成 phone_element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//a[contains(@class,'phoneNumberContainer')]")) ) print(phone_element.text)
- 处理完页面后切回列表页
关闭当前广告标签页,切回原列表页继续循环:
driver.close() driver.switch_to.window(original_window)
完整修复后代码
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 driver = webdriver.Chrome("E:\\Selenium\\Driver\\chromedriver.exe") driver.get("https://www.kijiji.ca/b-cars-trucks/edmonton/c174l1700203?adRemoved=4722799") # 等待列表元素加载完成 vehicleTitles = WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.XPATH, "//a[contains(@class,'title')]")) ) original_window = driver.current_window_handle for title in vehicleTitles: title_text = title.text print(title_text) # 打开新标签页 title.click() # 切换到新标签页 WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) for window_handle in driver.window_handles: if window_handle != original_window: driver.switch_to.window(window_handle) break try: # 点击显示号码按钮 show_phone_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(@class,'phoneNumberContainer')]")) ) show_phone_btn.click() # 提取并打印电话号码 phone_element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//a[contains(@class,'phoneNumberContainer')]")) ) print(f"电话号码: {phone_element.text}") except Exception as e: print(f"处理{title_text}时出错: {str(e)}") finally: # 关闭当前标签页并切回列表页 driver.close() driver.switch_to.window(original_window) driver.quit()
内容的提问来源于stack exchange,提问作者Muhammad Rizwan
相关产品推荐
相关产品推荐

