三大等待
1、三大等待:等待的方式有三種:強制等待,隱性等待,顯性等待。
-
1、強制等待:time.sleep(2),秒
- 優點:使用簡單
- 缺點:等待時間把握不準,容易造成時間浪費或者等待時間不足,不靈活
-
2、智能等待–在指定時間內(最長時間12,15s),什么時候成立,什么時候不等了
- 2.1、隱形等待:driver.implicitly_wait(“超時時長-秒”)
條件:等待一個元素被找到。 找元素都是從html當中去找。find_element,在html當中是存在的。
特征:在一個瀏覽器會話當中只需要被調用一次,所有的find_element都可以應用。
如果超時時長以內沒有找著元素,就會拋異常:NosuchElementException的找不到元素的異常。
優點:全局應用,它適用于WebDriver會話期間中所有查找的Web元素(通過findelement方法)
缺點:它只支持單一條件:元素存在;只能等待元素存在,不能適用條件
更復雜的情況,如:元素可點擊、元素可見 - 2.2、顯性等待:
注意:條件的參數必須要是元組或者列表的類型的:(元素定位的方法,元素定位表達式)
WebDriverWait(driver, 超時時間, 輪詢周期默認0.5).until(條件) 直到條件成立 ---- 用這個
WebDriverWait(driver, 超時時間, 輪詢周期默認0.5).until_not(條件) 直到條件不成立 -用的少
局部生效,哪里需要等待哪里就要調用,生效只有一次。
如果超時時長以內沒有找著元素,就會拋異常: TimeoutException,超時異常
優點:可以設置更加豐富的特定條件
缺點:僅對指定的元素生效,代碼略復雜 【但是后面框架封裝之后 封裝一次 后面調用】
presence_of_element_located(元組/列表) :給定的元素存在
visibility_of_element_located(元組/列表) :給定的元素可見
element_to_be_clickable(元組/列表) : 給定的元素可點擊
- 2.1、隱形等待:driver.implicitly_wait(“超時時長-秒”)
2、元素存在/可見/可用的區別: 元素存在< 可見< 可用
- 元素的存在: 能find_element就可以了。如果存在但不可見,是可以獲取元素屬性的,但是不能夠對元素進行操作。
元素的可見: 在存在的基礎上,元素在頁面上大小>0,即在頁面上顯示出來了 肉眼可見。
比如百度頁面上的設置按鈕,鼠標懸浮上去才會顯示菜單,那么默認情況下 這個元素是存在但不可見的:
style=‘display:None’; 不可見,這個元素是存在但是不可見。
style=‘display:block’ 元素展示出來了,存在并且可見。
元素的可用:在可見的基礎上,能夠使用其原始功能,比如可點擊,可輸入等
比如按鈕可點擊即可用,不可點擊即不可用。輸入框可輸入即可用,不可輸入即不可用。下拉列表可以選可用
3、find_element和 find_elements
- find_element — 在頁面當中找到匹配的第一個元素。返回的WebElement對象 【就算元素定位的表達式不唯一,也會返回找到第一個元素】
如果元素表達式能唯一盡量唯一,如果實在沒有辦法找到唯一的,你也可以使用這個不唯一方法 找到第一個元素。 - find_elements — 在頁面當中,找到匹配的所有元素。返回的列表。列表當中每個成員都是WebElement對象 --萬不得已的時候可以用,基本上很少用。
4、WebElement類當中定義常用的方法:
- send_keys() — 輸入 (Keys類定義了鍵盤上除了26個字母和0-9數字外其它的按鍵。)
- click() — 點擊操作
text — 獲取元素的文本內容(頁面操作之后某些元素的文本發生變化 或者 拿到這個文本用來做斷言) - get_attribute() — 獲取元素的屬性值
- clear() — 清除內容
- is_displayed() – 元素是否顯示 結果為布爾值,可以用來做斷言
2、三大切換
元素報錯找不到可能的原因有哪些?【F12里可找到這個元素 但是代碼執行報錯】
1)頁面需要加一些等待
2)窗口切換
3)iframe子頁面
4)頁面有彈框
- 1、窗口切換
- 當我們點擊了 a 標簽元素(超鏈接)時,會觸發打開鏈接頁面的事件,有兩種
情形:
1、在當前窗口加載新頁面內容
2、新建一個窗口加載新頁面內容,這種情況在 a 標簽有
target=“_blank” 時觸發。
當發生第2種情況時,我們需要切換窗口。在新的窗口里定位元素。
切換的步驟:
1)執行打開新窗口的操作
2)獲取現在所有的窗口句柄。
窗口列表 : wins = driver.window_handles ,結果是個列表,最新的
窗口在列表的最后。
新打開的窗口追加在窗口列表末尾。
通過索引進行選擇: wins[-1]獲取最新的窗口
3)切換到最新窗口:driver.switch_to.window(窗口列表[-1])
切換窗口-參數windowname(窗口的名字 也就是窗口句柄)
需要注意,窗口的句柄并不是固定的,而是由瀏覽器分配的,類似
于進程號: 窗口句柄是唯一,但是并不固定 ,所以不能直接寫死進
行切換。
需要通過獲取到所有句柄后的列表 取值
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
driver.maximize_window()
x_wait_click =(By.XPATH, '//a[contains(text(),"新聞")]')
WebDriverWait(driver, 5, 0.5).until(EC.element_to_be_clickable(x_wait_click)).click()
#打開新的tab頁,打開新聞的頁面
#第一步:獲取所有的窗口的句柄wins = driver.window_handlesprint(wins[-1])
# 第二步:取值切換新的窗口
driver.switch_to.window(wins[-1])
#//input[@id="ww"]
ww = (By.XPATH,'//input[@id="ww"]')
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located(ww)).send_keys("中國")time.sleep(2)
driver.quit()
- 2、多窗口切換:
'''
打開新的tab頁,打開新聞的頁面
第一步:獲取所有的窗口的句柄import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
driver.maximize_window()
news =(By.XPATH, '//a[contains(text(),"新聞")]')
map = (By.XPATH,'//a[contains(text(),"地圖")]')
post_par = (By.XPATH,'//a[contains(text(),"貼吧")]')
WebDriverWait(driver, 5, 0.5).until(EC.element_to_be_clickable(news)).click()
WebDriverWait(driver, 5, 0.5).until(EC.element_to_be_clickable(map)).click()
WebDriverWait(driver, 5, 0.5).until(EC.element_to_be_clickable(post_par)).click()
#打開新的tab頁,打開新聞的頁面
#第一步:獲取所有的窗口的句柄wins = driver.window_handles
print(driver.current_url)
print(wins)
ww = (By.XPATH,'//input[@id="ww"]')
for i in wins:if driver.current_url =="https://news.baidu.com/":breakelse:
# 取值切換新的窗口driver.switch_to.window(i)
WebDriverWait(driver,10,0.5).until(EC.visibility_of_element_located(ww)).send_keys("中國")time.sleep(2)
driver.quit()
-
2、iframe切換
-
- iframe是什么?
- iframe里面放的是另外一個html頁面。頁面嵌套
driver.find_element的時候,只在當前所在的html當中找元素,不可以
跨html的。所以,如果我們要操作iframe當中html里的元素,那么必須先切換到iframe當
中的html當中去
-
2.如何確認頁面是否有iframe的步驟:
- 第一個就是:明確元素定位正確且等待到位,依然找不到元素,那么有可能就是在iframe當中。
第二個就是:在元素定位的時候,查看上方的絕對路徑鏈接,如果其中有2個html,說明在iframe當中
- 第一個就是:明確元素定位正確且等待到位,依然找不到元素,那么有可能就是在iframe當中。
-
3、iframe切換的方法:driver.switch_to.frame(有2種方式)
- 第一種:通過iframe元素的name或者id屬性切換: 【QQ空間案例】
driver.switch_to.frame(“login_frame”)
注意: 如果id是變化的,也是不可以用于定位的,要換定位方法進
行定位; 如何確認是變化的,有數字+刷新確認。| 沒有id和name
屬性,也需要換方法定位并切換。
第二種:識別你要操作的元素是不是在iframe當中 【126.com案例】
- 第一種:通過iframe元素的name或者id屬性切換: 【QQ空間案例】
-
4、iframe退出
- 退出iframe
切到子頁面里,有時候需要退回到主頁面里定位,就需要退出iframe:
driver.switch_to.default_content() — 跳出iframe,回到默認的html當
中。如果有多層頁面嵌套,一下回到最外層頁面。
driver.switch_to.parent_frame() : 回到父級頁面中,只能一級一級的
跳出
注意:一個主頁面可能會存在多個iframe子頁面,要進去另外一個
iframe,就需要先退出 再進去另外一個。
- 退出iframe
-
-
3、彈框切換
-
彈窗切換【alert(警告消息框),confirm(確認消息框),prompt(提示消息對話框) 】
-
如果頁面發生了彈窗,要點擊彈窗元素,也要進行彈窗切換,不然定位不到元素。
彈窗有三種不同類型:alert(警告消息框)、confirm(確認消息框)、prompt(提示消息對話框)
通過switch_to.alert()切換到彈窗
再使用accept、dismiss、send_keys、text方法進行操作
1)alert彈框: 本質上是js的彈框 ,需要切換后將它關掉。 ==最常見 優先掌握
彈框出現后,要點擊確認,才會消失。操作:
accept(): 點擊確定
text: 獲取彈框文本
2)confirm(確認消息框): 確認和取消兩個選項,可以有如下操作:
dismiss(): 點擊取消
accept(): 點擊確定
text: 獲取彈框文本
3)prompt(提示消息對話框),可以輸入內容。 有如下四種操作:
dismiss(): 點擊取消
accept(): 點擊確定
text: 獲取框中的文本
send_keys(): 輸入文本
注意: prompt輸入文本,chrome瀏覽器不支持,Firefox支持,chrome瀏覽器的驅動bug -
4、如果元素定位不到,有哪些原因?【no suchelement 如何排查】
- 1、檢查我們的元素定位表達式是否寫錯,可以F12搜索驗證
2、檢查是否是需要加等待: 智能等待+ 強制登錄結合使用
3、檢查是否元素在iframe中,如果是的話就需要切換iframe
4、檢查元素是否在新的窗口中,如果是的話我們就需要切換窗口
5、檢查是否有彈框,需要點掉彈框再去定位;
6、是否元素不可見,先移動鼠標或者其他操作讓你可見后再操作 – 操作鼠標
7、是否無法直接操作,可以通過js 點擊 或者鍵鼠操作等。 – js點擊 后面會講
- 1、檢查我們的元素定位表達式是否寫錯,可以F12搜索驗證
-