1. 程式人生 > >selenium的三種等待方式

selenium的三種等待方式

 如今大多數的 web 應用程式使用 AJAX 技術。當瀏覽器在載入頁面時,頁面內的元素可能並不是同時被 加 載 完 成 的 , 這 給 元 素 的 定 位 添 加 的 困 難 。 如 果 因 為 在 加 載 某 個 元 素 時 延 遲 而 造 成ElementNotVisibleException 的情況出現,那麼就會降低的自動化指令碼的穩定性。WebDriver 提供了兩種型別的等待:顯式等待和隱式等待。

  • sleep 休眠方法 

有時間我們希望指令碼執行到某一位置時做固定時間的休眠,尤其是在指令碼除錯的過程中。那麼可以使用 sleep()方法,需要說明的是 sleep()由 Python 的 time 模組提供。

#coding=utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
sleep(2)
driver.find_element_by_id("kw").send_keys("webdriver")
driver.find_element_by_id("su").click()
sleep(3)
driver.quit()

當執行到 sleep()方法時會固定的休眠所設定的時長,然後再繼續執行。sleep()方法預設引數以秒為單
位,如果設定時長小於 1 秒,可以用小數點表示,如:sleep(0.5) 表示休眠0.5秒。

  • 隱式等待

隱式等待是通過一定的時長等待頁面所元素載入完成。哪果超出了設定的時長元素還沒有被載入測拋NoSuchElementException異常。WebDriver 提供了 implicitly_wait()方法來實現隱式等待,預設設定為 0。它的用法相對來說要簡單的多。driver.implicitly_wait(10) # 隱性等待,最長等10秒

#coding=utf-8
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
input_ = driver.find_element_by_id("kw22")
input_.send_keys('selenium')
driver.quit()

implicitly_wait()預設引數的單位為秒,本例中設定等待時長為 10 秒,首先這 10 秒並非一個固定的等
待時間,它並不影響指令碼的執行速度。其次,它並不真對頁面上的某一元素進行等待,當指令碼執行到某個
元素定位時,如果元素可定位那麼繼續執行,如果元素定位不到,那麼它將以輪詢的方式不斷的判斷元素
是否被定位到,假設在第 6 秒鐘定位到元素則繼續執行。直接超出設定時長(10 秒)還沒定位到元素則拋
出異常。
在上面的例子中,顯然百度輸入框的定位 id=kw22 是有誤的,那麼在超出 10 秒後將丟擲異常。 

  • 顯式等待 

顯式等待使 WebdDriver 等待某個條件成立時繼續執行,否則在達到最大時長時拋棄超時異常(TimeoutException)。

#coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = WebDriverWait(driver,5,0.5).until(
EC.presence_of_element_located((By.ID,"kw"))
)
element.send_keys('selenium')
driver.quit()

WebDriverWait()
它是由 webdirver 提供的等待方法。在設定時間內,預設每隔一段時間檢測一次當前頁面元素是否存在,如果超過設定時間檢測不到則丟擲異常。具體格式如下:

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

WebDriverWait(driver, 5,0.5).until( EC.presence_of_element_located((By.ID, "kw"))) 

driver - WebDriver 的驅動程式(Ie, Firefox,Chrome 等)
timeout - 最長超時時間,預設以秒為單位

poll_frequency - 休眠時間的間隔(步長)時間,預設為 0.5 秒
ignored_exceptions - 超時後的異常資訊,預設情況下拋 NoSuchElementException 異常。
until(method, message=’ ’)
呼叫該方法提供的驅動程式作為一個引數,直到返回值為 Ture。
until_not(method, message=’ ’)
呼叫該方法提供的驅動程式作為一個引數,直到返回值為 False。

Expected Conditions
在本例中,我們在使用 expected_conditions 類時對其時行了重新命名,通過 as 關鍵字對其重新命名為 EC,
並呼叫 presence_of_element_located()判斷元素是否存在。Expected Conditions類提供預期條件判斷方法請另行查閱。除了 expected_conditions 所提供的預期方法,通過 is_displayed()方法來判斷元素是否可見,檢視以下兩個例子。

#coding=utf-8
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
input_ = driver.find_element_by_id("kw")
element = WebDriverWait(driver,5,0.5).until(
lambda driver : input_.is_displayed()
)
input_.send_keys('selenium')
driver.quit()

lambad 為 Python 建立匿名函式的關鍵字。關於 Python 匿名函式的使用這裡不再進行講解,請參考Python 相關教程。
定義 input_為百度輸入框,通過 is_displayed()判斷其是否可見。 

from selenium import webdriver
from time import sleep,ctime

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")

print(ctime())
for i in range(10):
    try:
        el=driver.find_element_by_id("kw22")
        if el.is_displayed(): 
                        break
        except:pass
        sleep(1)
    else:
        print("time out")
    driver.close()
    print(ctime())
       

通過for迴圈10次,每次迴圈判斷元素的is_dispalyed()狀態是否為True:如果為True,則break跳出迴圈;否則sleep(1)後繼續迴圈判斷,直到10次迴圈結束後,列印“time out”資訊。