>[warning] 在實戰中,沒有設置好正確的元素等待,經常會出現元素找不著的異常報錯,導致自動化腳本非常不穩定。所以我們務必要理解并且在適當的位置設置好相應的元素等待,這是經驗之談!!!
[TOC]
## 設置元素等待的原因
如今大多數Web應用程序使用Ajax技術,**當瀏覽器在加載頁面時,頁面上的元素可能并不是同時被加載完成的**,這給元素的定位增加了困難。如果因為在加載某個元素時延遲而造成ElementNotVisibleException的情況出現,那么就會降低自動化腳本的穩定性,我們可以通過設置元素等待改善這種問題造成的不穩定。
## 設置元素等待
WebDriver提供了兩種類型的等待:**含蓄等待**和**明確等待**。<span style="color:red">明確等待作用于特定代碼塊</span>,使得WebDriver等待某個條件成立時繼續執行,否則在達到最大時長時拋出超時異常;而<span style="color:red">含蓄等待,屬于全局超時設置</span>,則會讓WebDriver在指定的時間內不斷輪詢DOM嘗試定位元素,直到成功定位元素或超時。
### 含蓄等待
implicitly_wait 屬于全局智能等待時間,一旦設置,作用于整個WebDriver生命周期,它不是固定的等待時間,一旦定位到元素就繼續往下執行。
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Chrome()
# 設置全局含蓄等待,設置后整個session期間都有效
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
element = driver.find_element_by_id("kw")
element.send_keys("selenium")
driver.close()
```
### 明確等待
方式一:比較極端的方式是通過`time.sleep()` 來讓程序休眠指定時間,然后繼續執行。
方式二:結合`WebDriverWait`和`ExpectedCondition`來設置等待。WebDriverWait 類是有WebDriver提供的等待方法,在設置時間內,默認每隔一段時間檢測一次當前頁面元素是否存在。具體格式如:
`WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)`
演示代碼:
```python
#!/usr/bin/env python
# -*- 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
import time
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
# 設置明確等待
wait = WebDriverWait(driver, 20, 0.5)
element = wait.until(EC.presence_of_element_located((By.ID, "kw")))
element.send_keys("selenium")
time.sleep(5)
driver.close()
```
代碼分析:如上代碼塊,打開百度首頁后,除非能定位到ID為“kw”的控件才繼續往下執行,否則將會一直等待到20s后拋出超時異常。WebDriverWait默認每500毫秒去檢查一次ExpectedCondition
### expected_conditions 預期條件
expected_conditions類所提供的預期條件判斷的方法如下:
* title_is(title):預期頁面標題匹配title
* title_contains(title):預期頁面標題包含title
* presence_of_element_located(locator):預期指定位置的元素出現在DOM中
* url_contains(url):預期url包含在當前頁面的url中
* url_to_be(url):預期url與當前頁面url完全匹配
* url_changes(url):預期url不等于當前頁面url
* visibility_of_element_located(locator):預期指定位置的元素可顯示出來
* visibility_of(element):預期指定元素對象可見
* text_to_be_present_in_element(locator, text_):預期指定文本與指定元素的文本相同
* text_to_be_present_in_element_value(locator, text_):預期指定文本與指定元素的屬性value值相同
* frame_to_be_available_and_switch_to_it(locator):預期指定的iframe是可以被切換的,并且自動切換到iframe中
* invisibility_of_element_located(locator):預期指定元素即不可見也不存在DOM中。
* element_to_be_clickable(locator):預期指定位置的元素是可見,并且可被點擊的。
* element_to_be_selected(element):預期指定元素是已選中的
* element_located_to_be_selected(locator):預期指定位置的元素是已
* alert_is_present():預期當前存在alert彈窗
<hr style="margin-top:50px">
<section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: 40px 0% 10px;box-sizing: border-box;"><section class="" style="display: inline-block;width: 100%;border-width: 5px;border-style: double;border-color: rgb(23, 22, 24);padding: 10px;border-radius: 2px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="transform: translate3d(20px, 0px, 0px);-webkit-transform: translate3d(20px, 0px, 0px);-moz-transform: translate3d(20px, 0px, 0px);-o-transform: translate3d(20px, 0px, 0px);font-size: 11px;margin: -50px 0% 0px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;width: 7em;height: 7em;display: inline-block;vertical-align: bottom;border-radius: 100%;border-width: 4px;border-style: double;border-color: rgb(23, 22, 24);background-position: center center;background-repeat: no-repeat;background-size: cover;background-image: url("http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n");"><section class="" style="width: 100%;height: 100%;overflow: hidden;box-sizing: border-box;"><img class="" data-ratio="0.6012024" data-w="499" data-src="http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n" style="opacity: 0; box-sizing: border-box; width: 100% !important; height: auto !important; visibility: visible !important;" width="100%" data-type="jpeg" _width="100%" src="http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n" data-fail="0"></section></section></section></section><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: -30px 0% 30px;box-sizing: border-box;"><section class="" style="display: inline-block;vertical-align: top;width: 61.8%;padding: 0px 15px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: 40px 0% 0px;box-sizing: border-box;"><section class="" style="color: rgb(160, 160, 160);box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">微信公眾號:</p><p style="margin: 0px;padding: 0px;box-sizing: border-box;">python測試開發圈</p><p style="margin: 0px;padding: 0px;box-sizing: border-box;"><br style="box-sizing: border-box;"></p></section></section></section></section><section class="" style="display: inline-block;vertical-align: top;width: 38.2%;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="text-align: center;margin: 10px 0% 0px;box-sizing: border-box;"><section class="" style="max-width: 100%;vertical-align: middle;display: inline-block;border-width: 0px;border-radius: 0px;box-shadow: rgb(0, 0, 0) 0px 0px 0px;width: 90%;overflow: hidden !important;box-sizing: border-box;"><img data-ratio="1" data-w="430" data-src="http://pav7h2emv.bkt.clouddn.com/FibGgIJSMfHtehzeWOOzjdQKSMx5" style="vertical-align: middle; max-width: 100%; box-sizing: border-box; width: 100% !important; height: auto !important; visibility: visible !important;" width="100%" data-type="jpeg" _width="100%" class="" src="http://pav7h2emv.bkt.clouddn.com/FibGgIJSMfHtehzeWOOzjdQKSMx5" data-fail="0"></section></section></section></section></section></section><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: -30px 0% 0px;box-sizing: border-box;"><section class="" style="display: inline-block;vertical-align: top;width: 61.8%;padding: 0px 15px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="transform: translate3d(5px, 0px, 0px);-webkit-transform: translate3d(5px, 0px, 0px);-moz-transform: translate3d(5px, 0px, 0px);-o-transform: translate3d(5px, 0px, 0px);box-sizing: border-box;"><section class="" style="color: rgb(160, 160, 160);font-size: 14px;box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">一起分享學習與成長路線</p></section></section></section></section><section class="" style="display: inline-block;vertical-align: top;width: 38.2%;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="transform: translate3d(10px, 0px, 0px);-webkit-transform: translate3d(10px, 0px, 0px);-moz-transform: translate3d(10px, 0px, 0px);-o-transform: translate3d(10px, 0px, 0px);box-sizing: border-box;"><section class="" style="color: rgb(160, 160, 160);font-size: 14px;box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">長按(或掃描)二維碼關注</p></section></section></section></section></section></section></section></section></section>