>[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(&quot;http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n&quot;);"><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>