核心概念

  1. WebDriverWait.until() 的本质
    python

    传入的是函数对象(函数地址),不是函数调用结果

    wait.until(函数对象) # ✅ 正确:传入函数本身
    wait.until(函数调用()) # ❌ 错误:传入函数返回值

  2. 返回值类型
    返回值取决于传入的条件函数返回什么,常见的有:
    ● WebElement 对象(最常见)
    ● Boolean 值
    ● List[WebElement] 列表
    ● 其他任何类型
    🔄 工作原理
    内部执行流程
    python

    伪代码展示 wait.until() 内部逻辑

    def until(self, method):
    for _ in range(重试次数):

     try:
         # 关键:调用传入的函数,并传递 driver
         result = method(self._driver)
         if result:  # 非 False/None
             return result
     except 允许的异常:
         pass
     sleep(轮询间隔)

    raise TimeoutException()
    🛠️ 两种使用方式
    方式一:使用 EC 模块(95% 场景)
    python
    from selenium.webdriver.support import expected_conditions as EC

简洁、可读性高

element = wait.until(EC.presence_of_element_located((By.ID, "id")))
element = wait.until(EC.element_to_be_clickable((By.CSS, ".btn")))
element = wait.until(EC.visibility_of_element_located((By.NAME, "name")))
方式二:自定义函数(5% 复杂场景)
python
def 自定义条件(driver):

# 复杂业务逻辑
if 条件1 and 条件2:
    return element
return False

result = wait.until(自定义条件)
🔗 闭包机制
EC 模块的闭包本质
python

EC 函数实际上是闭包工厂

def presence_of_element_located(locator):

def _predicate(driver):  # 闭包函数
    return driver.find_element(*locator)  # 使用外部的 locator
return _predicate  # 返回闭包

使用过程:

闭包 = EC.presence_of_element_located((By.ID, "test"))
元素 = wait.until(闭包) # wait 内部调用闭包并传入 driver
自定义闭包示例
python
def 创建文本检查器(元素ID, 期望文本):

def 检查函数(driver):  # 闭包
    element = driver.find_element(By.ID, 元素ID)
    return element if element.text == 期望文本 else False
return 检查函数  # 返回配置好的闭包

检查器 = 创建文本检查器("status", "完成")
结果 = wait.until(检查器)
💡 关键要点

  1. driver 的生命周期
    python

    driver 必须在 wait 之前创建

    driver = webdriver.Chrome() # 1. 创建驱动
    wait = WebDriverWait(driver, 10) # 2. 创建等待器
    元素 = wait.until(条件函数) # 3. 使用等待

  2. 参数传递机制
    ● WebDriverWait 创建时保存 driver 引用
    ● until() 调用时自动将 driver 传递给条件函数
    ● 条件函数的第一个参数接收这个 driver
  3. 异常处理
    python
    from selenium.common.exceptions import TimeoutException

try:

element = wait.until(条件函数)

except TimeoutException:

print("等待超时,元素未找到")

📊 使用建议
场景 推荐方案 示例
简单元素等待 EC 内置条件 EC.presence_of_element_located()
复杂业务逻辑 自定义函数 多条件组合判断
可复用条件 闭包工厂 创建带参数的等待条件
简单一次性 lambda lambda d: d.find_element(...).text == "x"
🎯 最佳实践
python

完整示例

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

class PageObject:

def __init__(self, driver):
    self.driver = driver
    self.wait = WebDriverWait(driver, 10)

def 安全操作(self):
    # 使用 EC 等待
    按钮 = self.wait.until(
        EC.element_to_be_clickable((By.ID, "submit"))
    )
    按钮.click()
    
    # 自定义复杂等待
    def 加载完成(driver):
        return "完成" in driver.find_element(By.ID, "status").text
    
    self.wait.until(加载完成)

总结
核心一句话:wait.until() 接受一个函数对象,WebDriverWait 会反复调用这个函数直到它返回非 False 值或超时。EC 模块提供了常用条件的闭包工厂,自定义函数处理复杂逻辑。


普郎特
20 声望65 粉丝

只有写出来的东西别人能看明白和有收获,才能说明自己是学懂了