博客 / 詳情

返回

Selenium WebDriverWait 原理總結

核心概念

  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 模塊提供了常用條件的閉包工廠,自定義函數處理複雜邏輯。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.