一、selenium的三種等待
當執行python的selenium程式碼時,如果需要定位一個元素或者點選一個元素,需要考慮到網速等多方面原因,導致頁面載入速度慢,元素還未載入出來,這樣就會導致找不到對應元素,從而報錯的問題,所以要設定等待條件,等待元素載入出來後才執行相應的程式碼。
其中,selenium中有三種等待方式,下面一一進行介紹。
1、強制等待
最簡單的一種方式,直接引入time模組,設定等待時間,但這種方式實用性不高,設定時間太短元素仍未找到,設定時間過長影響效率。
import time time.sleep(5)
2、顯式等待
原理:指定一個等待條件,和一個最長等待時間,程式會判斷在等待時間內條件是否滿足,如果滿足則返回,如果不滿足會繼續等待,超過時間就會丟擲異常。
(簡而言之,就是直到元素出現才去操作,如果超時則報異常)from selenium.webdriver import Chromefrom selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC browser = Chrome() # 瀏覽器物件 browser.get('http://www.baidu.com') # 訪問百度頁面 e = browser.find_element_by_id('kw') # 傳送資料,輸入文字 e.send_keys('檸檬班') # 快速點選,查詢父節點如果有form表單就會直接提交 e.submit() wait = WebDriverWait(browser, 20) e = wait.until(EC.visibility_of_element_located((By.XPATH, "//a[contains(text(), 'lemon.ke.qq.com/' )]"))) e = browser.find_element_by_xpath("//a[contains(text(), 'lemon.ke.qq.com/' )]") print(e)WebDriverWait(driver,timeout,poll_frequency
=
0.5
,ignored_exceptions
=
None
)
driver:瀏覽器驅動
timeout:最長超過時間,預設以秒為單位
poll_frequency:監測的時間間隔,預設為
0.5
秒
ignored_exceptions:超時後的異常資訊,預設情況下拋NoSuchElementException異常
WebDriverWait一般有until和until_not方法配合使用
until(method,message)
until_not(method ,message)
until中的所有方法:
title_is 標題是某內容
title_contains 標題包含某內容
presence_of_element_located 元素載入出,傳入定位元組,如(By.ID, 'p')
visibility_of_element_located 元素可見,傳入定位元組
visibility_of 可見,傳入元素物件
presence_of_all_elements_located 所有元素載入出
text_to_be_present_in_element 某個元素文字包含某文字
text_to_be_present_in_element_value 某個元素值包含某文字
frame_to_be_available_and_switch_to_it frame載入並切換
invisibility_of_element_located 元素不可見
element_to_be_clickable 元素可點選
staleness_of 判斷一個元素是否仍在DOM,可判斷頁面是否已經重新整理
element_to_be_selected 元素可選擇,傳元素物件
element_located_to_be_selected 元素可選擇,傳入定位元組
element_selection_state_to_be 傳入元素物件以及狀態,相等返回True,否則返回False
element_located_selection_state_to_be 傳入定位元組以及狀態,相等返回True,否則返回False
alert_is_present 是否出現Alert
3、隱式等待
原理:隱式等待,就是在建立driver時,為瀏覽器物件建立一個等待時間,這個方法是得不到某個元素就等待一段時間,直到拿到某個元素位置。
當使用了隱式等待執行測試的時候,如果 WebDriver沒有在 DOM中找到元素,將繼續等待,超出設定時間後則丟擲找不到元素的異常,換句話說,當查詢元素或元素並沒有立即出現的時候,隱式等待將等待一段時間再查詢 DOM,預設的時間是0。
缺點:侷限性高,只能用來等元素出現,或者是某個指令沒有完成,並不能等待所有情況,只能等待很少的一部分。
from selenium.webdriver import Chrome browser = Chrome() # 瀏覽器物件 # 開啟隱式等待,全域性只需放一次 browser.implicitly_wait(30) browser.implicitly_wait(10) # 等待十秒載入不出來就會丟擲異常,10秒內載入出來正常返回 browser.get('http://www.baidu.com') e = browser.find_element_by_id('kw') print(e)
implicity_wait()預設引數的單位為秒,本例中設定等待時長為10秒,首先這10秒並非一個固定的等待時間,它並不影響指令碼的執行速度。其次,它並不針對頁面上的某一元素進行等待。當指令碼執行到某個元素定位時,如果元素可以定位,則繼續執行,如果元素定位不到,則它將以輪詢的方式不斷地判斷元素是否被定位到。假設在第六秒定位到了元素則繼續執行,若直到超出設定的時長10秒還沒有定位到元素,則丟擲異常。
二、selenium的三種切換
1、視窗切換
原理:獲取開啟新視窗之前的控制程式碼(列表),然後在獲取開啟新視窗之後的控制程式碼,使用browser.switch_to.window(handles[-1])方法切換到最新視窗。
from selenium.webdriver import Chrome from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC browser = Chrome() # 瀏覽器物件 # 開啟隱式等待,全域性只需放一次 browser.implicitly_wait(30) # 30S之內只要元素出現就結束,每一個元素都有30S browser.get('http://www.baidu.com') e = browser.find_element_by_id('kw') # 型別e WebElement # 傳送資料,輸入文字 e.send_keys('檸檬班') # 快速點選,查詢父節點如果有form表單就會直接提交 e.submit() # 定定位百度一下 # e_submit = browser.find_element_by_id('su') # e_submit.click() # time.sleep(10) # 定時器 wait = WebDriverWait(browser, 20) e = wait.until(EC.visibility_of_element_located((By.XPATH, "//a[contains(text(), 'lemon.ke.qq.com/' )]"))) e = browser.find_element_by_xpath("//a[contains(text(), 'lemon.ke.qq.com/' )]") handles = browser.window_handles # 是一個列表 獲取控制程式碼的動作一定要放到click之前,因為new_window_is_opened是要比較控制程式碼數量 e.click() print(browser.window_handles) # 切換視窗,可能視窗沒開啟,也是需要等待的,必須要用顯示等待 # 定時器 wait = WebDriverWait(browser, 20) e = wait.until(EC.new_window_is_opened(handles))
browser.switch_to.window(handles[-1])
wait = WebDriverWait(browser, 20)
e = wait.until(EC.visibility_of_element_located((By.XPATH, "//h4[text()='華華老師']")))
# 找到華華 huahua = browser.find_element_by_xpath("//h4[text()= '華華老師' ]")
print(huahua)
注意:獲取控制程式碼的動作一定要放到click之前,因為new_window_is_opened是要比較控制程式碼數量。
2、iframe切換
from selenium.webdriver import Chrome from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC browser = Chrome() # 瀏覽器物件 # 開啟隱式等待,全域性只需放一次 browser.implicitly_wait(30) # 30S之內只要元素出現就結束,每一個元素都有30S browser.get('http://www.baidu.com') # iframe 等待 wait = WebDriverWait(browser, 20) e = wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//iframe[@name="iframe2"]'))) # 會自動進行切換,不用再單獨進行切換 # browser.switch_to.frame('iframe2') e = browser.find_element_by_id('kw') print(e) """ :Usage: driver.switch_to.frame('frame_name') driver.switch_to.frame(1) 索引 driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0]) webelement物件切換 """ iframe_e = browser.find_element_by_xpath('//iframe[@name="iframe2"]') browser.switch_to.frame(iframe_e)
3、彈框切換