>[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>