为何使用含变量的contains(text()) XPath表达式搜索耗时过长?
Selenium元素定位耗时过长的优化方案
问题核心原因
你当前的元素定位逻辑慢,不是超时时间设置的问题,主要是XPath表达式效率低下,每次循环都要遍历大量DOM节点,加上重复查询DOM的操作,导致耗时累积增加。
具体优化方案
1. 重构XPath表达式
原XPath先匹配文本再过滤class,会遍历所有包含目标文本的div节点后再筛选class,效率极低。改成先过滤class缩小范围,再匹配文本,能大幅减少遍历的节点数量:
# 精准匹配文本(适合文本无空格的情况) xpath = "//div[@class='Io6YTe fontBodyMedium' and text()='{}']".format(tlds[i]) # 处理文本含前后空格的情况 xpath = "//div[@class='Io6YTe fontBodyMedium' and normalize-space(text())='{}']".format(tlds[i])
2. 替换为CSS选择器
CSS选择器在浏览器中的解析效率普遍高于XPath,优先使用这种方式:
# 基础写法(部分浏览器支持:contains伪类) sito = WebDriverWait(driver, 0.2).until( EC.presence_of_element_located((By.CSS_SELECTOR, f"div.Io6YTe.fontBodyMedium:contains('{tlds[i]}')")) ).text
如果浏览器不支持:contains()伪类,用JS直接定位更高效:
script = f""" const elem = document.querySelector('div.Io6YTe.fontBodyMedium'); return elem && elem.textContent.trim() === '{tlds[i]}' ? elem : null; """ sito = driver.execute_script(script) sito = sito.text if sito else None
3. 一次性缓存目标元素
避免循环中重复查询DOM,先批量获取所有符合class的元素,再在本地内存中遍历匹配文本:
# 提前获取所有目标元素 try: target_elements = WebDriverWait(driver, 0.2).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div.Io6YTe.fontBodyMedium")) ) except: target_elements = [] # 本地遍历匹配 sito = None for elem in target_elements: elem_text = elem.text.strip() if elem_text in tlds: sito = elem_text print("T2") break
4. 确保页面处于稳定状态
如果页面未加载完成,即使设置短超时,WebDriver也会等待页面稳定。循环前先确认页面就绪:
# 等待文档完全加载完成 WebDriverWait(driver, 5).until(lambda d: d.execute_script("return document.readyState") == "complete")
优化后完整代码
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 先确保页面加载完成 WebDriverWait(driver, 5).until(lambda d: d.execute_script("return document.readyState") == "complete") # 提前获取所有目标元素 try: target_elements = WebDriverWait(driver, 0.2).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div.Io6YTe.fontBodyMedium")) ) except: target_elements = [] sito = None for elem in target_elements: elem_text = elem.text.strip() if elem_text in tlds: sito = elem_text print("T2") break if not sito: print("Cerca sito... 未找到匹配的TLD")
内容的提问来源于stack exchange,提问作者Lucian BodnareSKU
相关产品推荐
相关产品推荐

