1. 程式人生 > >Python + Selenium: 等待處理

Python + Selenium: 等待處理

我們前面介紹的Selenium的WebDriver測試方法是基於網頁來進行的。之前的例子都是用簡單的網頁來操作,可能體會不到網頁的載入過程,但實際應用過程中,網頁載入是要消耗一定的時間的。你的指令碼已經開始執行,但你要定位的元素卻還沒加載出來,此時就會報出一個找不到元素的錯誤。顯然,沒有考慮載入時間的指令碼不是一個成功的指令碼。今天我們就來介紹一下如何設定等待時間。

等待的三種方法

time.sleep(n)

強制等待n秒。Python本身的函式,包含在time包中,使用前需要匯入time包。我們之前的例項中經常會使用這種等待,方便大家能看清指令碼執行的結果。這種等待方法十分笨拙,無論頁面載入得如何,都必須等待n秒,可以說是十分不智慧了。

implicitly_wait(n)

最長等待n秒,若n秒內頁面載入完成,則提前結束等待。WebDriver提供的等待方法,也被稱為隱性等待,比強制等待聰明瞭一點,但如果頁面本身包含一個超大視訊之類的檔案,就算我們需要定位的元素在最開始已經加載出來,卻依舊要等待所有檔案載入結束之後,指令碼才能繼續執行,依舊算是有些弊端。

WebDriverWait(n)

最長等待n秒,n秒內每隔一段時間去檢查需要定位的元素是否存在,若存在則提前結束等待。也是WebDriver提供的等待方法,也被稱為顯性等待,這種等待比隱性等待更智慧了一些,無視整個頁面的載入,只要需要的元素存在了,就結束等待。

例項

強制等待在之前例子中都有使用過了,我們就來看一看WebDriver提供的兩種等待方法

隱性等待

其實隱性等待在之前的介紹中也有使用過,但沒有特別提到使用的方法。我們這次來開啟網易的首頁,這是一個載入內容很多的入口網站,根據網速不同,目測大概要10秒左右才能載入完畢,我們把等待時間設定為60秒,然後計算一下從開啟頁面到點選頁面導航欄中的【公開課】按鈕需要多久。

# coding = utf-8
from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.implicitly_wait(60) #隱性等待時間60秒
time_start = time.time() #記錄開啟頁面時的時間
driver.
get('https://www.163.com/') driver.find_element_by_id('js_love_url').click() time_end = time.time() #記錄點選按鈕後的時間 print('access time is : ', time_end - time_start) #列印時間差,即實際消耗時間 time.sleep(2) #強制等待2秒,為了觀察我們確實打開了【公開課】頁面 driver.quit()

指令碼執行結束可以看到,雖然我們設定了隱性時間為60秒,但5秒左右(看我下面的執行結果)頁面已載入完畢,可以點選【公開課】按鈕。下面是我的一次執行結果,顯示了整個載入時間。

>>>access time is :  5.717327117919922
顯性等待

顯性等待使用時需要匯入selenium.webdriver.support.wait.WebDriverWait類,API如下:

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
  • driver:不用說了,你定義的WebDriver瀏覽器(Chrome,Firefox等)
  • timeout:最長等待時間,單位為秒
  • poll_frequency:間隔查詢元素的時間,預設為0.5秒(不設定就是0.5秒),也就是說預設0.5秒去檢視一次要查詢的元素是否存在,找到了就結束整個顯性等待,否則繼續等待0.5秒再查詢一次
  • ignored_exceptions=None:超時傳送的異常資訊,預設傳送NoSuchElementException

由於顯性等待可能需要確認元素是否存在,一般還要配合以下兩個方法使用

until(method, message='')
until_not(method, message='')
  • method:until()的method意為將驅動程式提供的方法作為引數呼叫,直到返回為not False,until_not()的method就是直到返回為False
  • message:超時傳的異常資訊

注意,method()必須是可呼叫的方法,要有__call__()方法。上面的例子,我們重新寫一下。

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

driver = webdriver.Chrome()
class button():
    def __call__(self, driver):
        if driver.find_element_by_id('js_love_url'):
            return True
        else:
            return False 

driver.implicitly_wait(60)
time_start = time.time()
driver.get('https://www.163.com/')

# driver.find_element_by_id('js_love_url').click()
WebDriverWait(driver,2,0.5).until(button()) 
time_end = time.time()
print('access time is : ', time_end - time_start)
time.sleep(2)
driver.quit()

看完這個例子可能會有疑問,我顯性等待明明設定了是2秒,為什麼沒有報錯呢。因為我們同時也設定了隱性等待時間,兩者時間取最長的等待時間為實際等待時間,因此在這裡例子裡,等待的時間還是60秒。

總結

  1. Selenium可以採取三種等待,最智慧的為顯性等待WebDriverWait()
  2. 隱性等待和顯性等待同時存在時,取兩者中最長的等待時間為有效等待時間
  3. 顯性等待中的until(method())的method()為可呼叫方法,可以自己定義,也可以用匿名函式等方法,這個我們以後細談
  4. 隱性等待設定一次,即貫穿整個指令碼始終,強制等待則必須在每個需要等待之處設定

歡迎訂閱我的公眾號,第一時間收到文章推送哦

微信