))
WebDriverWait源码解读
class WebDriverWait(object):
def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
"""Constructor, takes a WebDriver instance and timeout in seconds.
:Args:
- driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
- timeout - Number of seconds before timing out
- poll_frequency - sleep interval between calls
By default, it is 0.5 second.
- ignored_exceptions - iterable structure of exception classes ignored during calls.
By default, it contains NoSuchElementException only.
WebDriverWait实例初始化传参
driver:WebDriver实例,传入前面声明的driver即可
timeout:最大超时时间;
poll_frequency:执行间隔,默认0.5s
ignored_exceptions:需要忽略的异常
如果在调用 until() 或 until_not() 的过程中抛出这个元组中的异常, 则不中断代码,继续等待;
如果抛出的是这个元组外的异常,则中断代码;
忽略的异常默认只有 NoSuchElementException
WebDriverWait实例的两个方法
until(self, method, message='')
作用:每隔一段时间(上面的poll_frequency)调用method,直到返回值不为False或不为空
method:需要执行的method
message:抛出异常时的文案,会返回 TimeoutException ,表示超时
注意:这个才是常用的,如:定位元素直到不返回空
until_not(self, method, message='')
作用:调用method,直到返回值为False或为空
method:需要执行的method
message:抛出异常时的文案,会返回 TimeoutException ,表示超时
两个方法的 method参数注意点
如果直接传入WebElement(页面元素)对象
WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))
则会抛出异常
TypeError: 'xxx' object is not callable
method 参数需要传入的对象必须包含 __call()__ 方法 ,什么意思?让对象可以直接被调用
官方提供的两个小例子
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId"))
is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).until_not(lambda x: x.find_element_by_id("someId").is_displayed())
可以看到,通过匿名函数也是可以的,可以说比后面介绍的 expected_conditions 模块要方便多了
那么有哪些是包含 __call()__ 的对象呢?
expected_conditions 模块(接下来重点讲的)
WebElement的 is_displayed() 、 is_enabled() 、 is_selected()
expected_conditions源码解读
expected_conditions的介绍
是selenium中的一个模块,包含一系列用于判断的条件类,一共26个类
这里就只介绍两个在设置元素等待里面最常用的判断条件类
其一:presence_of_element_located
class presence_of_element_located(object):
""" An expectation for checking that an element is present on the DOM
of a page. This does not necessarily mean that the element is visible.
locator - used to find the element
returns the WebElement once it is located
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
return _find_element(driver, self.locator)
检查当前DOM树种是否存在该元素(和是否可见没有关系),只要有一个元素加载出来则通过
locator参数
传入一个元组,格式如下 (By.ID, "元素ID")
第一个参数:定位元素的方式,和那八种元素定位方式一样,只是这里需要引入 By 模块,然后再调用类属性
第二个参数:和之前调用元素定位方法一样传参即可
所以正确写法是: presence_of_element_located((By.ID, "kw"))
一起来看看By模块的源码
class By(object):
Set of supported locator strategies.
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
其二:presence_of_all_elements_located
源码几乎一样
class presence_of_all_elements_located(object):
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
return _find_elements(driver, self.locator)
唯一要注意的点就是
因为调用的是 _find_elements ,会返回多个元素
如果用这个条件类,必须等所有匹配到的元素都加载出来才通过