现在很多Web应用都在使用AJAX技术。浏览器载入一个页面时,页面内的元素可能是在不同的时间载入的,
这会加大定位元素的困难程度,因为元素不在DOM里,会抛出 ElementNotVisibleException
异常,
使用 waits
,我们就可以解决这个问题。Waiting给(页面)动作的执行提供了一些时间间隔-通常是
元素定位或者其他对元素的操作。
Selenium WebDriver提供了两类 waits
- 隐式和显式。显式的 waits
会让WebDriver在更深
一步的执行前等待一个确定的条件触发,
隐式的 waits
则会让WebDriver试图定位元素的时候对DOM进行指定次数的轮询。
显式的 waits
等待一个确定的条件触发然后才进行更深一步的执行。
最糟糕的的做法是 time.sleep()
,这指定的条件是等待一个指定的时间段。
这里提供一些便利的方法让你编写的代码只等待需要的时间,WebDriverWait
结合
ExpectedCondition
是一种实现的方法:
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_delay_loading") try: element = WebDriverWait(driver,10).until( EC.presence_of_element_located((By.ID,"myDynamicElement")) ) finally: driver.quit()
这段代码会等待10秒,如果10秒内找到元素则立即返回,否则会抛出 TimeoutException
异常,
WebDriverWait默认每500毫秒调用一下 ExpectedCondition``直到它返回成功为止。
``ExpectedCondition
类型是布尔的,成功的返回值就是true,其他类型的 ExpectedCondition
成功的返回值就是 not null
Expected Conditions
自动化网页操作时,有许多频繁使用到的通用条件。下面列出的是每一个条件的实现。 Selenium + Python 提供了许多方便的方法,因此你不需要自己编写 expected_condition 的类, 或者创建你自己的通用包
- title_is
- title_contains
- presence_of_element_located
- visibility_of_element_located
- visibility_of
- presence_of_all_elements_located
- text_to_be_present_in_element
- text_to_be_present_in_element_value
- frame_to_be_available_and_switch_to_it
- invisibility_of_element_located
- element_to_be_clickable - it is Displayed and Enabled.
- staleness_of
- element_to_be_selected
- element_located_to_be_selected
- element_selection_state_to_be
- element_located_selection_state_to_be
- alert_is_present
from selenium.webdriver.support import expected_conditions as EC wait = WebDriverWait(driver,10) element = wait.until(EC.element_to_be_clickable((By.ID,'someid')))
expected_conditions
模块包含了一系列预定义的条件来和WebDriverWait使用
当我们要找一个或者一些不能立即可用的元素的时候,隐式 waits
会告诉WebDriver轮询DOM指定的次数,默认设置是0次。
一旦设定,WebDriver对象实例的整个生命周期的隐式调用也就设定好了。
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')