如何使用Selenium检测两个元素中任意一个是否可见?
使用Selenium检测两个元素任意一个可见性的解决方案
问题场景
页面包含搜索框与结果列表:
- 搜索到内容时,显示结果列表
- 未搜索到内容时,显示
No Results Found提示
需要实现逻辑:
- 判断当前状态是「结果列表可见」还是「无结果提示可见」
- 无结果时,将搜索文本加入未找到列表;有结果时,点击对应结果
页面HTML结构(React渲染,结果列表会替换无结果提示的容器)
<div class="related-files-adder"> <div class="MuiFormControl-root MuiTextField-root MuiFormControl-fullWidth"> <div class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-fullWidth MuiInput-fullWidth MuiInputBase-formControl MuiInput-formControl"> <input placeholder="Search..." type="text" class="MuiInputBase-input MuiInput-input"> <!-- 搜索输入框 --> </div> </div> <div class="this is where the both no results and the table lives"> <div> <!-- 该容器会被结果列表替换 --> <p class="lead">No Results Found</p> </div> </div> </div>
已尝试方法的问题
- 错误使用
EC.any_of
直接调用EC.visibility_of_element_located作为判断条件,会始终返回true——因为该方法返回的是等待条件对象,而非布尔值,无法直接用于if判断:
if (EC.visibility_of_element_located((By.XPATH, restultsTablePath))): print("即使显示无结果,这里也会输出true") if (EC.visibility_of_element_located((By.XPATH, noResultsPath))): print("即使显示结果列表,这里也会输出true")
find_element().is_displayed()抛出异常
当元素不存在时,find_element会直接抛出NoSuchElementException,导致代码崩溃:
if (driver.find_element(By.XPATH, restultsTablePath).is_displayed()): print("表格可见时正常,不可见时直接崩溃")
- 关于元素过时(staleness)的疑问
React渲染会替换DOM元素,不确定应该监听哪个元素的过时状态。
解决方案
方案1:结合WebDriverWait与EC.any_of(推荐)
正确使用等待条件,等待两个元素中任意一个可见,同时处理React渲染的页面更新:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException wait = WebDriverWait(driver, 10) # 先获取结果容器的父元素,等待它过时(React重新渲染后该元素会被替换) parent_container = driver.find_element(By.CSS_SELECTOR, "div.related-files-adder > div:nth-child(2)") wait.until(EC.staleness_of(parent_container)) try: # 等待任意一个元素可见 visible_element = wait.until(EC.any_of( EC.visibility_of_element_located((By.XPATH, restultsTablePath)), EC.visibility_of_element_located((By.XPATH, noResultsPath)) )) # 判断当前是哪种状态 if "No Results Found" in visible_element.text: # 无结果,将搜索文本加入列表 not_found_list.append(search_text) else: # 有结果,点击对应元素(示例:点击第一行结果) visible_element.find_element(By.XPATH, "./tbody/tr[1]").click() except TimeoutException: # 处理超时情况(如页面加载失败) print("页面超时,未找到目标元素")
方案2:使用find_elements避免异常
find_elements会返回匹配元素的列表(无匹配时返回空列表),不会抛出异常,可结合is_displayed()判断可见性:
# 检查结果列表是否存在且可见 results_tables = driver.find_elements(By.XPATH, restultsTablePath) if results_tables and results_tables[0].is_displayed(): # 有结果,执行点击操作 results_tables[0].find_element(By.XPATH, "./tbody/tr[1]").click() else: # 检查无结果提示是否存在且可见 no_results = driver.find_elements(By.XPATH, noResultsPath) if no_results and no_results[0].is_displayed(): # 无结果,加入列表 not_found_list.append(search_text)
关于元素过时的处理
React会替换结果容器内的DOM元素,因此可以监听父容器(即包含结果列表/无结果提示的div)的过时状态,确保页面完成渲染后再进行判断,避免获取到旧的DOM元素。
内容的提问来源于stack exchange,提问作者dbarnes
相关产品推荐
相关产品推荐

