我正在使用Selenium 2 / WebDriver和Python API,如下所示:
from selenium.webdriver.support import expected_conditions as EC
# code that causes an ajax query to be run
WebDriverWait(driver, 10).until( EC.presence_of_element_located( \
(By.CSS_SELECTOR, "div.some_result")));
我想等待 结果返回(div.some_result
)或一个“未找到”字符串。那可能吗?种类:
WebDriverWait(driver, 10).until( \
EC.presence_of_element_located( \
(By.CSS_SELECTOR, "div.some_result")) \
or
EC.presence_of_element_located( \
(By.CSS_SELECTOR, "div.no_result")) \
);
我意识到我可以使用CSS选择器(div.no_result, div.some_result
)来做到这一点,但有没有办法使用Selenium期望条件方法来做到这一点?
答案 0 :(得分:14)
我是这样做的:
class AnyEc:
""" Use with WebDriverWait to combine expected_conditions
in an OR.
"""
def __init__(self, *args):
self.ecs = args
def __call__(self, driver):
for fn in self.ecs:
try:
if fn(driver): return True
except:
pass
然后称之为......
from selenium.webdriver.support import expected_conditions as EC
# ...
WebDriverWait(driver, 10).until( AnyEc(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "div.some_result")),
EC.presence_of_element_located(
(By.CSS_SELECTOR, "div.no_result")) ))
显然,同样实施AllEc
课程也是微不足道的。
的Nb。 try:
块是奇数。我很困惑,因为有些EC返回true / false而其他EC会抛出False的异常。 WebDriverWait捕获异常,因此我的AnyEc产生奇怪的结果,因为第一个抛出异常意味着AnyEc没有进行下一次测试。
答案 1 :(得分:4)
古老的问题但是,
在独立于selenium的示例中考虑WedDriverWait
的工作原理:
def is_even(n):
return n % 2 == 0
x = 10
WebDriverWait(x, 5).until(is_even)
is_even(x)
返回True
现在,WebDriverWait(7, 5).until(is_even)
将花费5秒钟,并引发TimeoutException
原来,您可以返回任何非Falsy值并捕获它:
def return_if_even(n):
if n % 2 == 0:
return n
else:
return False
x = 10
y = WebDriverWait(x, 5).until(return_if_even)
print(y) # >> 10
现在考虑EC
的方法是如何工作的:
print(By.CSS_SELECTOR) # first note this is only a string
>> 'css selector'
cond = EC.presence_of_element_located( ('css selector', 'div.some_result') )
# this is only a function(*ish), and you can call it right away:
cond(driver)
# if element is in page, returns the element, raise an exception otherwise
你可能想尝试类似的东西:
def presence_of_any_element_located(parent, *selectors):
ecs = []
for selector in selectors:
ecs.append(
EC.presence_of_element_located( ('css selector', selector) )
)
# Execute the 'EC' functions agains 'parent'
ecs = [ec(parent) for ec in ecs]
return any(ecs)
如果在EC.presence_of_element_located
中找不到False
时selector
返回parent
,那么这可行,但它会引发异常,一个易于理解的解决方法是:< / p>
def element_in_parent(parent, selector):
matches = parent.find_elements_by_css_selector(selector)
if len(matches) == 0:
return False
else:
return matches
def any_element_in_parent(parent, *selectors):
for selector in selectors:
matches = element_in_parent(parent, selector)
# if there is a match, return right away
if matches:
return matches
# If list was exhausted
return False
# let's try
any_element_in_parent(driver, 'div.some_result', 'div.no_result')
# if found in driver, will return matches, else, return False
# For convenience, let's make a version wich takes a tuple containing the arguments (either one works):
cond = lambda args: any_element_in_parent(*args)
cond( (driver, 'div.some_result', 'div.no_result') )
# exactly same result as above
# At last, wait up until 5 seconds for it
WebDriverWait((driver, 'div.some_result', 'div.no_result'), 5).until(cond)
我的目标是解释,artfulrobot已经提供了一般用于实际EC
方法的片段,请注意
class A(object):
def __init__(...): pass
def __call__(...): pass
只是一种更灵活的方式来定义函数(实际上,类似函数&#39;,但在此上下文中无关紧要)
答案 2 :(得分:1)
并非完全通过EC,但确实取得了相同的结果-有所收获。
仍使用WebDriverWait
的{{1}}方法,但在lambda表达式内传递纯until()
方法:
find_elements_*()
WebDriverWait(driver, 10).until(lambda driver: driver.find_elements_by_id("id1") or \
driver.find_elements_by_css_selector("#id2"))[0]
方法返回所有匹配元素的列表,如果没有,则返回一个空元素-这是布尔值false。因此,如果第一个调用没有找到任何内容,则对第二个调用进行评估;重复直到他们中的一个找到匹配项,或者时间用完为止。
红利-当它们返回值时,末尾的索引find_elements_*()
实际上将为您返回匹配的元素-如果在后续调用中有任何用途,则为之。
答案 3 :(得分:-1)
尝试使用lambda表达式:
[HttpGet]
public HttpResponseMessage ReadVendor(int vendorId)
WebDriverWait(driver, 10).until(lambda a: