當有元素定位不到時,好比下拉框,彈出框等各類定位不到時;python
通常是兩種問題:1 、有frame ;二、沒有加等待web
下面學習三種等待方式:ajax
2.1 強制等待 sleep(xx)或者Time.sleep
是在程序運行過程當中使用time模塊中的sleep進行代碼的休眠進行強制等待,是顯式等待中的一種極端狀況。瀏覽器
這種方法簡單粗暴,無論瀏覽器是否加載完,程序都要等待規定的xx時間,時間到了才繼續執行下面的代碼。框架
不建議老是用這種等待方式,會嚴重影響程序的執行速度。經過time模塊中sleep進行代碼的暫停,可是實際使用過程當中,若是都以sleep進行控制嚴重影響了程序的運行。dom
2.1.1 參考代碼1
# coding=utf-8🔥 # 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行 # 2.註釋:包括記錄建立時間,建立人,項目名稱。 ''' Created on 2019-12-10 @author: 北京-宏哥 QQ交流羣:705269076 Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試 ''' # 3.導入模塊 import time # 強制等待——代碼休眠 from selenium import webdriver driver = webdriver.Chrome() driver.get("https://www.baidu.com") time.sleep(3) driver.quit()
2.1.2 參考代碼2
# coding=utf-8🔥 # 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行 # 2.註釋:包括記錄建立時間,建立人,項目名稱。 ''' Created on 2019-12-10 @author: 北京-宏哥 QQ交流羣:705269076 Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試 ''' # 3.導入模塊 from selenium import webdriver from time import sleep driver = webdriver.Chrome() driver.get('https://www.baidu.com/') sleep(3)#強制性等待3s再執行如下代碼 print(driver.current_url) driver.quit()#退出驅動,關閉全部窗口
2.2 隱性等待 implicitly_wait(xx)
這種方法是設置一個最長的等待時間,若是在規定時間內網頁所有元素加載完成,則執行下一步,不然一直等待時間截止才執行下一步。比強制性等待智能些編輯器
!隱性等待對整個driver的週期都起做用,因此只要設置一次便可函數
2.2.1 參考代碼1
# coding=utf-8🔥
# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行
# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥 QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''
# 3.導入模塊
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException from time import ctime driver = webdriver.Firefox() # 設置隱式等待爲10秒 driver.implicitly_wait(10) driver.get("http://www.baidu.com") try: print(ctime()) driver.find_element_by_id("kw22").send_keys('selenium') except NoSuchElementException as e: print(e) finally: print(ctime()) driver.quit()
這裏能夠看到在10秒內沒有找到想要找到的元素,可是依舊執行了10秒,而後報錯,若是修改代碼爲能夠找到,代碼執行很是迅速。post
implicitly_wait()默認參數的單位爲秒,本例中設置等待時長爲10秒。首先這10秒並不是一個固定的等待時間,它並不影響腳本的執行速度。其次,它並不針對頁面上的某一元素進行等待。當腳本執行到某個元素定位時,若是元素能夠定位,則繼續執行;若是元素定位
不到,則它將以輪詢的方式不斷地判斷元素是否被定位到。假設在第6秒定位到了元素則繼續執行,若直到超出設置時長(10秒)尚未定位到元素,則拋出異常。
2.2.2 參考代碼2
# coding=utf-8🔥 # 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行 # 2.註釋:包括記錄建立時間,建立人,項目名稱。 ''' Created on 2019-12-10 @author: 北京-宏哥 QQ交流羣:705269076 Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試 ''' # 3.導入模塊 from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.baidu.com/') driver.implicitly_wait(30)#隱性等待,最長30s print(driver.current_url) driver.quit()
2.3.顯性等待 WebDriverWait
WebDriverWait配合該類的until()和until_not()方法,根據條件靈活的等待
程序每隔xx秒看一眼,若是條件成立了,則執行下一步,不然繼續等待,直到超過設置的最長時間,而後拋出TimeoutException。
顯式等待是你在代碼中定義等待必定條件發生後再進一步執行你的代碼。
A. 使用前,先引用相關庫
B. 肯定元素的定位表達式
C. 使用expected_conditions對應的方法來生成判斷條件
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.ID,ele_locator)))
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.XPATH,ele_locator)))
D. 調用WebDriverWait類設置等待總時長、輪詢週期
2.3.1 參考代碼1
# coding=utf-8🔥 # 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行 # 2.註釋:包括記錄建立時間,建立人,項目名稱。 ''' Created on 2019-12-10 @author: 北京-宏哥 QQ交流羣:705269076 Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試 ''' # 3.導入模塊 #A. 使用前,先引用相關庫 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome()#打開Chrome瀏覽器 driver.get('https://www.baidu.com/')#打開百度 driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()#點擊【登陸】;click() 方法,可模擬在按鈕上的一次鼠標單擊。 # B. 肯定元素的定位表達式 ele_locator = "TANGRAM__PSP_10__footerULoginBtn"#經過id,肯定‘用戶名登陸’元素 # C. 使用expected_conditions對應的方法來生成判斷條件 # EC.方法名(定位方式,定位表達式) # EC.visibility_of_element_located(By.ID,ele_locator)#元素可見 # D. 調用WebDriverWait類設置等待總時長、輪詢週期 # WebDriverWait(driver, 超時時長, 調用頻率(默認0.5s)).until(可執行方法, 超時時返回的信息) # 等待10秒鐘,每隔1秒去查看對應的元素是否可見;若是可見,繼續下一步操做;若是不可見,則繼續等待,直到10s結束,若是元素仍是不可見,則拋出超時異常 WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.ID,ele_locator))) driver.find_element_by_id('TANGRAM__PSP_10__footerULoginBtn').click()#點擊【用戶名登陸】 driver.close()#關閉當前窗口
2.3.2 參考代碼2
# coding=utf-8🔥
# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行
# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥 QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''
# 3.導入模塊
from time import ctime
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 dr = webdriver.Chrome() dr.get('https://www.baidu.com') try: print(ctime()) element = WebDriverWait(dr, 10).until( EC.presence_of_element_located((By.ID, "kw")) ) # WebDriverWait(driver=self.driver, timeout=300, poll_frequency=0.5, ignored_exceptions=None) # driver:瀏覽器驅動 # timeout:最長超時等待時間 # poll_frequency:檢測的時間間隔,默認爲500ms # ignore_exception:超時後拋出的異常信息,默認狀況下拋 NoSuchElementException 異常 print("我已找到") finally: print(ctime()) dr.quit()
執行結果:
以上代碼執行後就發現,整段代碼執行速度很是快,即便我在WebDriverWait中設置10秒,也不會等待10秒的狀況,由於在不到一秒內,已經完成了加載並定位id爲「kw」的元素。
經過WebDriverWait 和 ExpectedCondition 組合使用,讓咱們的代碼執行只須要等待須要的時長,而不是固定的時長,這樣最大限度的節省時間。
此外ExpectedCondition類中提供了不少預期條件判斷方法,省去了再建立包的功夫:
""" title_is:判斷當前頁面的title是否等於預期 title_contains:判斷當前頁面的title是否包含預期字符串 presence_of_element_located:判斷某個元素是否被加到了dom樹裏,並不表明該元素必定可見 visibility_of_element_located:判斷某個元素是否可見. 可見表明元素非隱藏,而且元素的寬和高都不等於0 visibility_of:跟上面的方法作同樣的事情,只是上面的方法要傳入locator,這個方法直接傳定位到的element就行了 presence_of_all_elements_located:判斷是否至少有1個元素存在於dom樹中。舉個例子,若是頁面上有n個元素的class都是'column-md-3',那麼只要有1個元素存在,這個方法就返回True text_to_be_present_in_element:判斷某個元素中的text是否 包含 了預期的字符串 text_to_be_present_in_element_value:判斷某個元素中的value屬性是否包含了預期的字符串 frame_to_be_available_and_switch_to_it:判斷該frame是否能夠switch進去,若是能夠的話,返回True而且switch進去,不然返回False invisibility_of_element_located:判斷某個元素中是否不存在於dom樹或不可見 element_to_be_clickable - it is Displayed and Enabled:判斷某個元素中是否可見而且是enable的,這樣的話才叫clickable staleness_of:等某個元素從dom樹中移除,注意,這個方法也是返回True或False element_to_be_selected:判斷某個元素是否被選中了,通常用在下拉列表 element_located_to_be_selected element_selection_state_to_be:判斷某個元素的選中狀態是否符合預期 element_located_selection_state_to_be:跟上面的方法做用同樣,只是上面的方法傳入定位到的element,而這個方法傳入locator alert_is_present:判斷頁面上是否存在alert """
另外這裏使用了until()函數也可使用until_not()
until_not(method, message='')
調用該方法體提供的回調函數做爲一個參數,直到返回值爲False
until(method, message='')
調用該方法體提供的回調函數做爲一個參數,直到返回值爲True