2013-05-09 32 views
13

我使用硒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)做到這一點,但有沒有辦法用料條件方法硒辦呢?

+0

看看這個http://stackoverflow.com/questions/7781792/selenium- waitforelement,可以幫助你.. – 2013-05-09 12:56:28

+0

ExpectedConditions類是一個整潔的一切,但我已經知道它不是非常可靠的(純粹的形式),你需要明確地捕捉使用它的有關例外情況,有時循環到重試失敗。 – djangofan 2013-05-09 23:39:12

回答

12

我做了這樣的:

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,而其他的會拋出False的異常。 WebDriverWait捕獲異常,所以我的AnyEc產生了奇怪的結果,因爲第一個拋出異常意味着AnyEc沒有進入下一個測試。

-2

嘗試使用lambda表達式:

WebDriverWait(driver, 10).until(lambda a:
a.presence_of_element_located(By.CSS_SELECTOR, "div.some_result") OR a.presence_of_element_located(By.CSS_SELECTOR, "div.no_result"))

1

古老的問題,而是,

考慮如何WedDriverWait的作品,在一個例子獨立硒:

def is_even(n): 
    return n % 2 == 0 

x = 10 

WebDriverWait(x, 5).until(is_even) 

這將等待秒鐘返回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 

你可能會想嘗試一些喜歡的東西E:

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返回Falseparent沒有發現selector,但它拋出一個異常,易於理解的解決辦法是:

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 sel 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: 
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 

只是一個更靈活的方式來定義函數(實際上,'功能樣',但在這種情況下,這是無關的)