显式等待的核心原理

显式等待通过条件触发机制实现精准等待,避免固定休眠。WebDriverWait 配合 expected_conditions 模块,可检测 DOM 状态变化、元素可见性等 20+ 种条件。典型场景包括元素出现(presence_of_element_located)、可点击状态(element_to_be_clickable)等。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, timeout=10)
element = wait.until(EC.presence_of_element_located((By.ID, "dynamic-content")))

超时异常处理策略

TimeoutException 需配合 try-except 实现优雅降级。建议设置多级等待策略:首次等待采用较长超时(10-15秒),重试时缩短等待时间(3-5秒)。日志记录需包含失败时的页面状态(如截图、HTML 片段)。

from selenium.common.exceptions import TimeoutException
try:
    element = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".loading")))
except TimeoutException:
    driver.save_screenshot("timeout_error.png")
    raise ElementNotVisibleError("Loading indicator not disappeared")

复合等待条件构建

通过逻辑运算符组合多个条件应对复杂场景。and_ / or_ 可创建组合条件,例如等待元素可见且包含特定文本。自定义条件函数需返回非 None 值或布尔值。

from selenium.webdriver.support.wait import WebDriverWait 
def element_contains_class(locator, class_name):
    def predicate(driver):
        element = driver.find_element(*locator)
        return class_name in element.get_attribute("class")
    return predicate

wait.until(element_contains_class((By.ID, "status"), "ready"))

动态加载模式识别

针对不同异步加载类型采用差异化策略:

  • XHR 请求:监控 network 活动或特定 JS 变量
  • 虚拟滚动:检测 scrollHeight 变化停止
  • 懒加载:触发 intersection observer 后等待图片加载完成
// 通过MutationObserver监听DOM变化
const observer = new MutationObserver(() => {
  if(document.querySelectorAll('.item').length >= 10) {
    observer.disconnect();
    window.__LOAD_COMPLETE = true;
  }
});
observer.observe(document.getElementById('container'), {childList: true});

性能优化最佳实践

  1. 避免隐式等待与显式等待混用,防止累积超时
  2. 设置合理的 polling_frequency(默认0.5秒),高频检测场景可缩短至0.1秒
  3. 对稳定元素使用 presence_of_element_located,动态元素使用 visibility_of
  4. 关键操作后添加稳定状态检查,例如等待进度条消失
  5. 采用分层超时配置:基础操作3-5秒,文件上传等特殊操作单独设置
# 分层超时配置示例
SHORT_TIMEOUT = 3
LONG_TIMEOUT = 15
def wait_for_ajax_complete(driver):
    return driver.execute_script("return jQuery.active == 0")

WebDriverWait(driver, LONG_TIMEOUT).until(wait_for_ajax_complete)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐