Waits
现在很多Web应用都在使用AJAX技术。浏览器载入一个页面时,页面内的元素可能是在不同的时间载入的,这会加大定位元素的困难程度,因为元素不在DOM里,会抛出ElementNotVisibleException
异常,使用waits
,我们就可以解决这个问题。Waiting给(页面)动作的执行提供了一些时间间隔-通常是元素定位或者其他对元素的操作。
Selenium WebDriver提供了两类waits
- 隐式和显式。显式的waits
会让WebDriver在更深一步的执行前等待一个确定的条件触发,隐式的waits
则会让WebDriver试图定位元素的时候对DOM进行指定次数的轮询。
显式Waits
显式的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
详细的ExpectedCondition
可以参看 7.6 浏览器驱动
预期条件
自动化网页操作时,有许多频繁使用到的通用条件。下面列出的是每一个条件的实现。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 - 元素展示并且可用
- 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
当我们要找一个或者一些不能立即可用的元素的时候,隐式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')
以下根据stackoverflow网友回答添加:原问题链接 推荐一直用显式的,忘记还有隐式吧(Always use explicit wait. Forget that implicit wait exists)
显示waits: 明确的行为表现 在本地的selenium运行(你选择的编程语言) 可以在任何你能想到的条件下工作 返回成功或者超时 可以定义元素的缺失为条件 可以定制重试间隔,可以忽略某些异常
隐式waits: 不明确的行为表现,同一个问题依赖于不同的操作系统,不同的浏览器,不同的selenium版本会有各种不同的表现 在远程的selenium上运行(控制浏览器的那部分). 只能在寻找元素的函数上工作 返回找到元素或者(在超时以后)没有找到 如果检查元素缺失那么总是会等待到超时 除了时间啥都不能指定