Selenium 等待機制:編寫穩定可靠的自動化腳本

一、為什么需要等待機制?

網頁是動態加載的,元素出現的時間不確定。如果腳本在元素還沒加載完成時就嘗試操作它,就會拋出?NoSuchElementException?異常。

三種等待方式:

  1. 強制等待time.sleep()?- 簡單但低效

  2. 隱式等待driver.implicitly_wait()?- 全局設置

  3. 顯式等待WebDriverWait?+?expected_conditions?-?最推薦的方式


二、強制等待 (不推薦但需了解)

import timetime.sleep(5) # 強制等待5秒
  • 優點:簡單易用

  • 缺點

    • 效率低下(總是等待固定時間)

    • 不可靠(網絡慢時可能不夠,網絡快時浪費時間)


三、隱式等待 (Implicit Wait)

設置一個全局的等待時間,對所有元素查找操作都生效。

from selenium import webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(10) # 設置隱式等待時間為10秒driver.get("https://example.com")
# 所有find_element操作都會最多等待10秒
element = driver.find_element(By.ID, "some-element")
  • 工作原理:在查找元素時,如果立即沒找到,會輪詢DOM直到找到元素或超時

  • 優點:一次設置,全局生效

  • 缺點

    • 不夠靈活,無法針對特定條件等待

    • 可能會影響腳本性能


四、顯式等待 (Explicit Wait) -?重點推薦

顯式等待允許你設置特定條件,只在需要的地方等待,更加靈活和高效。

1. 基本用法

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By# 創建WebDriverWait實例,設置最長等待時間10秒
wait = WebDriverWait(driver, 10)# 等待直到元素可見
element = wait.until(EC.visibility_of_element_located((By.ID, "myDynamicElement")))# 等待直到元素可點擊
element = wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))# 然后進行操作
element.click()

2. 常用的 Expected Conditions

Selenium 提供了許多預定義的條件,以下是最常用的幾種:

元素存在與可見性
  • presence_of_element_located(locator)?- 元素出現在DOM中(不一定可見)

  • visibility_of_element_located(locator)?- 元素可見(有寬度和高度)

  • invisibility_of_element_located(locator)?- 元素不可見或不存在

元素可交互性
  • element_to_be_clickable(locator)?- 元素可見且可點擊

  • element_to_be_selected(locator)?- 復選框/單選框可被選中

文本內容
  • text_to_be_present_in_element(locator, text)?- 元素包含特定文本

  • text_to_be_present_in_element_value(locator, text)?- 元素的value屬性包含特定文本

頁面狀態
  • title_is(title)?- 頁面標題完全匹配

  • title_contains(partial_title)?- 頁面標題包含特定文本

  • url_to_be(url)?- URL完全匹配

  • url_contains(partial_url)?- URL包含特定文本

元素選擇狀態
  • element_located_to_be_selected(locator)?- 元素被選中

  • element_located_selection_state_to_be(locator, is_selected)?- 元素選中狀態符合預期

元素數量
  • presence_of_all_elements_located(locator)?- 至少找到一個元素

  • number_of_elements_to_be(locator, number)?- 找到特定數量的元素

  • number_of_elements_to_be_less_than(locator, number)?- 元素數量少于指定值

  • number_of_elements_to_be_more_than(locator, number)?- 元素數量多于指定值

3. 自定義等待條件

如果預定義條件不滿足需求,你可以創建自定義等待條件:

from selenium.webdriver.support.ui import WebDriverWait# 自定義等待函數 - 等待元素包含特定類名
def element_has_class(locator, class_name):def predicate(driver):element = driver.find_element(*locator)if class_name in element.get_attribute("class").split():return elementreturn Falsereturn predicate# 使用自定義等待條件
wait = WebDriverWait(driver, 10)
element = wait.until(element_has_class((By.ID, "my-element"), "active"))

4. 高級用法:設置輪詢頻率和忽略異常

from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException# 設置等待時間10秒,每0.5秒檢查一次,忽略NoSuchElementException異常
wait = WebDriverWait(driver, timeout=10, poll_frequency=0.5,ignored_exceptions=[NoSuchElementException]
)element = wait.until(EC.visibility_of_element_located((By.ID, "my-element")))

五、混合使用等待策略

最佳實踐是結合使用隱式等待和顯式等待:

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 Bydriver = webdriver.Chrome()
# 設置一個較短的隱式等待作為后備
driver.implicitly_wait(5)driver.get("https://example.com")try:# 使用顯式等待處理關鍵元素wait = WebDriverWait(driver, 10)login_button = wait.until(EC.element_to_be_clickable((By.ID, "login-btn")))login_button.click()# 等待頁面跳轉完成(URL變化)wait.until(EC.url_contains("dashboard"))# 等待歡迎消息出現welcome_message = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "welcome-msg")))print("登錄成功:" + welcome_message.text)finally:driver.quit()

六、實戰示例:處理動態加載內容

假設有一個頁面,點擊按鈕后通過AJAX加載內容:

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
from selenium.webdriver.common.keys import Keysdriver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)driver.get("https://example.com/dynamic-content")# 點擊加載更多按鈕
load_more_btn = wait.until(EC.element_to_be_clickable((By.ID, "load-more")))
load_more_btn.click()# 等待新內容加載完成(等待特定元素出現)
# 方法1:等待新增的元素
new_item = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='item'][last()]"))
)# 方法2:等待加載指示器消失
wait.until(EC.invisibility_of_element_located((By.ID, "loading-spinner"))
)# 方法3:等待特定數量的元素
wait.until(EC.number_of_elements_to_be((By.CLASS_NAME, "item"), 10)
)print("新內容加載完成!")
driver.quit()

七、常見問題與解決方案

1. 等待超時怎么辦?

from selenium.common.exceptions import TimeoutExceptiontry:element = wait.until(EC.visibility_of_element_located((By.ID, "slow-element")))
except TimeoutException:print("元素加載超時,執行備用方案")# 執行其他操作或重新加載頁面driver.refresh()# 再次嘗試等待element = wait.until(EC.visibility_of_element_located((By.ID, "slow-element")))

2. 處理StaleElementReferenceException

當元素不再附加到DOM時會發生此異常,常見于頁面刷新或AJAX更新后:

from selenium.common.exceptions import StaleElementReferenceExceptiondef wait_for_non_stale_element(locator, timeout=10):wait = WebDriverWait(driver, timeout)return wait.until(lambda d: d.find_element(*locator))element = wait_for_non_stale_element((By.ID, "dynamic-element"))

3. 等待多個條件

# 使用lambda表達式組合多個條件
wait.until(lambda d: d.find_element(By.ID, "element1").is_displayed() and d.find_element(By.ID, "element2").is_enabled()
)

八、最佳實踐總結

  1. 優先使用顯式等待:針對特定條件等待,更加精確和高效

  2. 合理設置超時時間:根據網絡速度和頁面復雜度設置

  3. 使用合適的預期條件:根據具體需求選擇最匹配的條件

  4. 避免混合使用隱式和顯式等待:可能導致不可預測的等待時間

  5. 處理異常:使用try-except塊處理可能的超時異常

  6. 編寫自定義等待條件:當內置條件不滿足需求時

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/95244.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/95244.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/95244.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

蓓韻安禧活性葉酸獨立包裝防漏貼心設計

蓓韻安禧葉酸新升級 近期,蓓韻安禧在葉酸產品上進行了重要的優化升級。這次升級的核心在于產品形態和使用體驗的顯著提升,尤其體現在其包裝設計上。新版本采用了獨立密封的小包裝形式,每一份都精準包含每日所需的葉酸量。這種設計不僅有效避免…

8針腳的1.8寸IIC接口的TFT彩屏的八個引腳都需要使用嗎?

核心結論 不需要全部使用8個引腳。實際僅需連接 4根核心線(GND, VCC, SCL, SDA) 即可基本工作,其余引腳為功能增強或備用設計。具體需根據屏幕型號確認,但通用規則如下:8針腳功能分解引腳標號典型名稱是否必需作用不連…

刷題日記0831

今日計劃5道早上起來不困,吃好早飯開始困了,感覺刷不動題,就先做別的事,不困。現在別的事做好了,感覺能刷動題了。開始開始。7/5134. 加油站 中等超時了。看下題解。不是,怎么上數學了?假設從 x…

【2025.8.31】自學Java三個月,談談心路歷程順便給自己灌點雞湯

自學Java三個月,談談心得順便給自己灌點雞湯 6月1開始上班,到今天剛好三個月。從上班第一天決定開始自學java,到今天也是正好3個月整,想借這個機會簡單記錄一下學習java的契機和進度,α一些碎碎念。(括號恐…

linux內核trace_begin和trace_end使用分析

1,strace/ftrace的實現和使用 echo 1 > /sys/kernel/debug/tracing/tracing_on echo function > /sys/kernel/debug/tracing/current_tracer 2, 手動插入追蹤點 在內核代碼中,可以使用trace_printk函數手動插入追蹤點,標記代碼段的開始和結束: trace_printk(&…

Linux-驅動積累

Linux 設備驅動概述?Linux 設備驅動是內核與硬件交互的核心橋梁,負責屏蔽硬件細節、提供統一操作接口。其以內核模塊為主要存在形式,支持動態加載 / 卸載,核心功能涵蓋硬件初始化、中斷處理、電源管理及數據傳輸,是嵌入式 Linux …

軟考-系統架構設計師 決策支持系統(DSS)詳細講解

個人博客:blogs.wurp.top 一、DSS的核心概念與定位 1. 什么是DSS? DSS是一個交互式的、計算機化的系統,旨在幫助決策者利用數據和模型來解決半結構化(Semi-structured) 或非結構化(Non-structured&#…

《Python 實戰:構建一個可擴展的訂單管理系統,從基礎操作到架構思維》

《Python 實戰:構建一個可擴展的訂單管理系統,從基礎操作到架構思維》 一、引言:用代碼管理商業的脈搏 在數字化浪潮席卷各行各業的今天,訂單管理系統已成為電商、物流、零售等領域的核心支撐。它不僅承載著交易數據,更是企業運營效率的體現。而 Python,以其簡潔優雅的…

【計算機網絡】生產問題排查:如何使用Wireshark抓包/讀取抓包文件進行網絡分析

1 緣起 有一次,公司同事A讓同事B看一次請求日志, 同事B說先抓一次包看看請求是否進入服務器-某個服務, 我知道這個事情后,也“參觀”了抓包過程, 上面的事件只是一個小插曲,緊接著的第二件事才是寫本篇文章的真正動機: 同一天,同事C讓同事D配置個服務代理(某種上網方…

網格dp|

lc3665class Solution {public:int uniquePaths(vector<vector<int>>& grid) {const int MOD 1000000007;int m grid.size(), n grid[0].size();vector memo(m, vector(n, array<int, 2>{-1, -1})); // -1 表示沒有計算過auto dfs [&](this auto…

煩人的Nano 編輯器,如何退出呢?

對于不熟悉 nano 編輯器的人來說&#xff0c;它的退出方式確實有點反直覺。別擔心&#xff0c;這是幾乎所有新手都會遇到的困惑。 退出 Nano 編輯器的正確方法 記住這個黃金法則&#xff1a;ctrl鍵是你的朋友&#xff01; 1. 正常保存并退出&#xff08;最常用&#xff09; 按 …

IDM(Internet Download Managerv 6.38)破除解版下載!IDM 下載器永久免費版!提升下載速度達5倍!安裝及使用

軟件介紹 IDM&#xff08;Internet Download Manager&#xff09;是一款功能強大的 Windows 平臺專業下載加速工具&#xff0c;可加速下載速度、調度任務、續傳下載、管理文件。可使下載速度提升至普通瀏覽器的 5 倍以上&#xff0c;最高可加速 8 倍。IDM 支持 HTTP、FTP、HTTP…

學習Java29天(tcp多發多收)但是無解決客戶端啟動多個問題

180/189今天看了一些ip的東西WLAN的ip是路由器隨機分配的&#xff08;DHCP&#xff09;

Photoshop - Ps Camera Raw 濾鏡

使用Adobe Photoshop Camera Raw濾鏡對圖像進行快速和可逆的編輯。Camera Raw濾鏡將圖像拖入Photoshop工作區&#xff0c;或者點擊菜單欄-文件-打開來打開圖像。選中圖像的對應的圖層&#xff0c;點擊菜單欄-濾鏡-Camera Raw濾鏡&#xff0c;彈出Camera Raw濾鏡面板。使用Camer…

Node.js(4)—— http模塊基礎

下面我們來學nodejs中的http模塊。在此之前&#xff0c;你需要有一定的網絡知識儲備&#xff0c;能知道http&#xff0c;IP&#xff0c;端口是什么并且它們之間的關系。如果還不清楚或比較模糊&#xff0c;可以查看下面的文章&#xff1a; HTTP協議與IP 下面我們開始學習。 目…

后端去拿數據怎么拿?

簡單來說&#xff0c;Entity 和 DTO 代表了數據在不同層次和場景下的不同形態和目的。它們最根本的區別在于&#xff1a;職責和目的不同。一句話概括Entity&#xff1a;代表數據庫中的表&#xff0c;是業務邏輯的核心&#xff0c;與持久化&#xff08;數據庫&#xff09;緊密相…

從源碼角度來學習Activit的啟動流程

免責聲明&#xff1a;本文是本人的學習記錄文檔&#xff0c;有問題可以評論區指出&#xff0c;謝謝 一、從Launcher點擊桌面圖標&#xff0c;拉起app進程&#xff08;不同進程間拉組件&#xff09; 從桌面點擊icon圖標拉起進程&#xff0c;這個就涉及到很多邏輯了&#xff0c;我…

pgAdmin介紹(PostgreSQL數據庫管理軟件)數據庫客戶端、PG客戶端、PostgreSQL客戶端

文章目錄**1. 安裝 pgAdmin****1.1 下載****1.2 安裝步驟&#xff08;以 Windows 為例&#xff09;**1. **運行安裝程序**&#xff1a;雙擊下載的 .exe 文件。2. **接受協議**&#xff1a;點擊 Next&#xff0c;勾選 I accept the agreement。3. **選擇安裝路徑**&#xff1a;默…

桌面GIS軟件FlatGeobuf轉Shapefile代碼分享

桌面GIS軟件FlatGeobuf轉Shapefile代碼分享1、后端代碼分享2、前端代碼分享分享完成

【Bluedroid】A2DP Source 音頻傳輸停止流程及資源管理機制(btif_a2dp_source_stop_audio_req)

本文深入剖析Android藍牙協議棧中A2DP音頻傳輸停止流程,涵蓋從用戶請求觸發、工作線程調度、資源釋放到性能統計的全鏈路實現。通過分析btif_a2dp_source_stop_audio_req到btif_a2dp_source_audio_tx_stop_event的代碼執行路徑,揭示多線程環境下的競爭規避策略、硬件抽象層(H…