4, 等待
如今, 大多数 web 应用程序都在使用 Ajax 技术. 当浏览器加载页面时, 该页面中的元素可能会以不同的时间间隔加载. 这使定位元素变得困难: 如果 DOM 中尚不存在元素, 则定位函数将引发 ElementNotVisibleException 异常. 使用等待, 我们可以解决此问题. 等待在执行的动作之间提供了一定的松弛时间 - 主要是定位元素或对该元素进行的任何其他操作.
Selenium Webdriver 提供两种类型的等待 - 隐式和显式. 显式等待使 WebDriver 等待特定条件发生, 然后再继续执行. 隐式等待使 WebDriver 在尝试查找元素时轮询 DOM 一定时间.
显示等待情况下, 只有特定条件触发后, WebDriver 才会继续执行后续操作. 隐式等待情况下, WebDriver 等待一定时间, 该时间段内, 如果特定元素没加载成功, 则抛出异常.
显式等待 Explicit Waits
显示等待的代码定义了等待条件, 只有该条件触发, 才执行后续代码
- 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
- driver = webdriver.Firefox()driver.get("http://somedomain/url_that_delays_loading")
- try:
- element = WebDriverWait(driver, 10).until(
- EC.presence_of_element_located((By.ID, "myDynamicElement")))
- finally:
- driver.quit()
上面的代码最多等待 10 秒, 超时后就抛出 TimeoutException, 假设在第 3 秒就找到了这个元素, 那么也就不会多等剩下的 7 秒使时间, 而是继续执行后续代码. WebDriverWait 默认每 500 毫秒调用一次 ExpectedCondition 中的方法, 直到它返回成功信号, 如果成功, 则返回相应的内容, 否则返回布尔类型的 False
- from selenium.webdriver.support import expected_conditions as EC
- wait_result = WebDriverWait(driver=self.driver, timeout=300, poll_frequency=0.5, ignored_exceptions=None).until(
- EC.text_to_be_present_in_element((By.XPATH, '//*[@id="VolumeTable"]/tbody/tr[1]/td[4]/label'), u'可用'))
driver: 浏览器驱动
timeout: 最长超时等待时间
poll_frequency: 检测的时间间隔, 默认为 500ms
ignore_exception: 超时后抛出的异常信息, 默认情况下抛 NoSuchElementException 异常
配合使用的 until() 或者 until_not() 方法说明:
until(method, message='')
调用该方法体提供的回调函数作为一个参数, 直到返回值为 True
until_not(method, message='')
调用该方法体提供的回调函数作为一个参数, 直到返回值为 False
模块包含一套预定义的条件集合. 大大方便了 WebDriverWait 的使用.
* * *
Expected Conditions 类提供的预期条件判断方法
在进行浏览器自动化的时候, 有一些条件是经常出现的, 下面列出的是每个条件的实现. Selenium Python binding provides some convienence 提供了很多实用的方法, 因此, 你无须再去编写 expected_condition class 或是创建你自己的工具包来实现这个工作.
title_is: 判断当前页面的 title 是否等于预期
title_contains: 判断当前页面的 title 是否包含预期字符串
presence_of_element_located: 判断某个元素是否被加到了 dom 树里, 并不代表该元素一定可见
visibility_of_element_located: 判断某个元素是否可见. 可见代表元素非隐藏, 并且元素的宽和高都不等于 0
visibility_of: 跟上面的方法做一样的事情, 只是上面的方法要传入 locator, 这个方法直接传定位到的 element 就好了
presence_of_all_elements_located: 判断是否至少有 1 个元素存在于 dom 树中. 举个例子, 如果页面上有 n 个元素的 class 都是'column-md-3', 那么只要有 1 个元素存在, 这个方法就返回 True
text_to_be_present_in_element: 判断某个元素中的 text 是否 包含 了预期的字符串
text_to_be_present_in_element_value: 判断某个元素中的 value 属性是否包含了预期的字符串
frame_to_be_available_and_switch_to_it: 判断该 frame 是否可以 switch 进去, 如果可以的话, 返回 True 并且 switch 进去, 否则返回 False
invisibility_of_element_located: 判断某个元素中是否不存在于 dom 树或不可见
element_to_be_clickable - it is Displayed and Enabled: 判断某个元素中是否可见并且是 enable 的, 这样的话才叫 clickable
staleness_of: 等某个元素从 dom 树中移除, 注意, 这个方法也是返回 True 或 False
element_to_be_selected: 判断某个元素是否被选中了, 一般用在下拉列表
element_located_to_be_selected
element_selection_state_to_be: 判断某个元素的选中状态是否符合预期
element_located_selection_state_to_be: 跟上面的方法作用一样, 只是上面的方法传入定位到的 element, 而这个方法传入 locator
alert_is_present: 判断页面上是否存在 alert
- Implicit Waits(隐式等待)
- from selenium import webdriver
- driver = webdriver.Firefox()
- driver.implicitly_wait(10) # seconds
- driver.get("http://somedomain/url_that_delays_loading")
- myDynamicElement = driver.find_element_by_id("myDynamicElement")
来源: http://www.bubuko.com/infodetail-3461505.html