You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无对应元素时获取元素数量且不触发WebDriver隐式等待?

如何在不触发WebDriver隐式等待的情况下获取元素数量(元素不存在时)

我需要在页面不存在指定元素时,以最优方式获取元素数量且不触发WebDriver的隐式等待。目前我的实现代码如下:

def get_number_of_elements(self, by, locator):
    self.driver.implicitly_wait(0)
    elements = self.driver.find_elements(by, locator)
    self.driver.implicitly_wait(self.config.IMPLICIT_TIMEOUT)
    return len(elements)

该方案可行,但想知道是否有更优的实现方式?


更新说明

问题源于webdriver.Chrome的实例化方式,简言之,请勿设置driver.implicitly_wait(),示例代码如下:

import time

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

if __name__ == '__main__':
    options = Options()
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--crash-dumps-dir=tmp')
    options.add_argument('--remote-allow-origins=*')
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-gpu")
    options.page_load_strategy = "eager"
    options.add_experimental_option("excludeSwitches", ["enable-automation"])

    driver = webdriver.Chrome(options=options)

    driver.set_page_load_timeout(30)
    # driver.implicitly_wait(30) # <-- 若开启此设置,当元素不存在时find_elements会触发30秒隐式等待
    driver.set_script_timeout(30)

    driver.get("https://www.google.com")
    driver.find_element(By.XPATH, "//div[text()='Accept all']").click()
    driver.find_element(By.NAME, "q").send_keys("Stack Overflow")
    driver.find_element(By.XPATH, "//input[@type='submit'][@value='Google Search']").submit()

    elements = driver.find_elements(By.XPATH, "//h1[text()='No such thing...']")
    print(len(elements))
    elements = driver.find_elements(By.XPATH, "//a")
    print(len(elements))

    time.sleep(5)
    driver.close()

更优实现方案

你的当前方案通过临时修改隐式等待时间来避免等待,虽然可行,但频繁修改全局等待配置可能引发竞态条件(比如多线程场景下的冲突)。以下是几种更优的思路:

1. 全局禁用隐式等待(推荐)

如更新说明所示,初始化ChromeDriver时不调用driver.implicitly_wait()。此时find_elements()方法会立即返回查询结果——无论元素是否存在,都不会触发等待逻辑。这种方式无需额外代码处理,简洁且无潜在风险,适合全局不需要隐式等待的场景。

2. 使用显式等待替代临时修改隐式等待

如果全局必须保留隐式等待,可以通过显式等待设置0秒超时,配合presence_of_all_elements_located条件来获取元素列表,更贴合Selenium最佳实践:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def get_number_of_elements(self, by, locator):
    elements = WebDriverWait(self.driver, 0).until(
        EC.presence_of_all_elements_located((by, locator))
    )
    return len(elements)

注意:部分Selenium版本中设置0秒等待可能仍有微小延迟,此时优先选择第一种方案。

3. 直接执行JavaScript查询元素

通过原生JavaScript查询元素,完全绕开WebDriver的等待机制,执行效率最高,且不受隐式等待配置影响:

from selenium.webdriver.common.by import By

def get_number_of_elements(self, by, locator):
    # 根据定位方式生成对应的JavaScript查询脚本
    if by == By.ID:
        js_script = f"return document.getElementById('{locator}') ? 1 : 0;"
    elif by == By.CLASS_NAME:
        js_script = f"return document.getElementsByClassName('{locator}').length;"
    elif by == By.TAG_NAME:
        js_script = f"return document.getElementsByTagName('{locator}').length;"
    elif by == By.NAME:
        js_script = f"return document.getElementsByName('{locator}').length;"
    elif by == By.XPATH:
        js_script = f"""
            return document.evaluate("{locator}", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength;
        """
    else:
        # 默认处理CSS_SELECTOR等其他定位方式
        js_script = f"return document.querySelectorAll('{locator}').length;"
    return self.driver.execute_script(js_script.strip())

内容的提问来源于stack exchange,提问作者Scott Deagan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:15:33