在 Selenium 脚本中,等待是一个核心问题。不加等待可能会遇到:

  • NoSuchElementException
  • ElementNotInteractableException
  • StaleElementReferenceException

这是因为页面元素未加载完就被访问。本文介绍 Selenium 中的三种等待机制:强制等待、隐式等待、显式等待,及其最佳使用场景。


🧨 等待问题示例

driver.get("https://example.com")
driver.find_element(By.ID, "submit").click()  # 页面还没加载好就执行,容易失败

🕐 一、强制等待(sleep)

import time
time.sleep(3)  # 暂停 3 秒

📌 特点:

  • 简单粗暴,无论页面是否加载完成都会等待固定时间
  • 会拖慢测试效率
  • 不推荐长期使用,只适用于调试或短暂缓冲

🧩 二、隐式等待(implicit wait)

driver.implicitly_wait(10)

📌 特点:

  • 设置一次,对整个 WebDriver 实例全局生效
  • 找不到元素时会等待最多 N 秒,直到找到或超时
  • 不适用于需要等待某些特定状态(如元素可点击)

🔁 示例:

driver.implicitly_wait(5)
driver.find_element(By.ID, "username").send_keys("admin")

🔍 三、显式等待(WebDriverWait)

显式等待是最推荐、最灵活的等待方式。

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

element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "submit"))
)

📌 支持多种条件判断:

  • presence_of_element_located(元素存在于 DOM 中)
  • visibility_of_element_located(元素可见)
  • element_to_be_clickable(元素可见且可点击)
  • text_to_be_present_in_element(某元素中包含指定文本)

✅ 示例:等待元素可点击

from selenium.webdriver.common.by import By

btn = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "login-button"))
)
btn.click()

🧼 三者对比总结

类型 是否推荐 使用方式 优点 缺点
强制等待 ❌ 不推荐 time.sleep(x) 简单 阻塞时间固定,效率低
隐式等待 ⚠️ 一般 driver.implicitly_wait(x) 设置简单,全局生效 精度差,容易被覆盖
显式等待 ✅ 推荐 WebDriverWait + EC.xxx 灵活、可组合判断 需手动写逻辑

🔥 实战建议

  • 尽量使用 显式等待,针对具体页面行为进行条件判断
  • 隐式等待和显式等待不要混用,可能产生冲突
  • 尽量避免使用 sleep(),除非确实无法判断加载状态

💬 常用显式等待条件(EC)

EC.presence_of_element_located
EC.visibility_of_element_located
EC.element_to_be_clickable
EC.invisibility_of_element_located
EC.text_to_be_present_in_element

文档参考:selenium.webdriver.support.expected_conditions


📌 延伸阅读:

  • 如何封装自定义等待工具类
  • 如何处理 AJAX 加载页面的动态等待
  • Selenium 和 Playwright 中等待机制对比

添加微信