2013-10-15 12 views
13

Sto provando a scrivere la mia condizione prevista. Quello di cui ho bisogno ... Ho un iframe. e ho anche un'immagine in esso. Voglio continuare l'elaborazione quando cambiò l'immagine. Quello che ho fatto:Python Selenium WebDriver. Sto scrivendo la mia condizione prevista

class url_changed_condition(object): 
    ''' 
    Checks whether url in iframe has changed or not 
    ''' 
    def __init__(self, urls): 
     self._current_url, self._new_url = urls 

    def __call__(self, ignored): 
     return self._current_url != self._new_url 

e successivamente nel codice che ho:

def process_image(self, locator, current_url): 
    try: 
     WebDriverWait(self.driver, 10).until(ec.presence_of_element_located((By.TAG_NAME, u"iframe"))) 
     iframe = self.driver.find_element(*locator) 
     if iframe: 
      print "Iframe found!" 
     self.driver.switch_to_frame(iframe) 
     WebDriverWait(self.driver, 10).until(ec.presence_of_element_located((By.XPATH, u"//div"))) 

     # WebDriverWait(self.driver, 10).until(
      # url_changed_condition(
       # (current_url, self.driver.find_element(By.XPATH, u"//a/img").get_attribute(u"src")))) 

     img_url = self.driver.find_element(By.XPATH, u"//a/img").get_attribute(u"src") 
     print img_url 
     self.search_dict[self._search_item].append(img_url) 
     self.driver.switch_to_default_content() 
    except NoSuchElementException as NSE: 
     print "iframe not found! {0}".format(NSE.msg) 
    except: 
     print "something went wrong" 
     import traceback 
     import sys 
     type_, value_, trace_ = sys.exc_info() 
     print type_, value_ 
     print traceback.format_tb(trace_) 
    finally: 
     return current_url 

questo codice funziona, ma restituisce lo stesso URL più volte. Il problema è quando ho decomposto url_changed_condition cade con TimeoutException in
(current_url, self.driver.find_element(By.XPATH, u"//a/img").get_attribute(u"src"))
La riga sotto funziona bene ... Non capisco.

risposta

1

Secondo il documentation:

WebDriverWait di default chiama l'ExpectedCondition ogni 500 millisecondi finché non ritorna con successo. Un risultato positivo è per Il tipo ExpectedCondition è valore restituito booleano true o not null per tutti gli altri tipi di ExpectedCondition.

Il fatto di ottenere lo stesso URL più volte se si commenta l'attesa personalizzata dovrebbe fornire un suggerimento.

In __call__() si restituisce sempre False poiché gli URL non cambiano mai. Dato che stai restituendo False, la Condizione prevista non viene mai soddisfatta e ottieni il TimeoutException.

Quindi, ridefinire la logica ExpectedCondition o verificare un caso diverso.

+0

mi stai dicendo esattamente quello che ho conosciuto. La tua risposta è esattamente ciò che ho codificato qui. Ho bisogno di 'self.driver.find_element (By.XPATH, u" // a/img "). Get_attribute (u" src ")' per essere chiamato ogni 500 millisecondi per confrontare il suo valore di ritorno con quello che ho già ricevuto. E quando non sono uguali il mio '__call __()' restituirà 'True'. –

+0

Stavo solo spiegando perché hai ottenuto il 'TimeoutException', dato che nella tua domanda non sembravi capire perché. Come ho detto, il tuo problema è che stai controllando l'elemento sbagliato (dal momento che l'URL apparentemente non cambia mai), o il periodo di timeout è troppo basso. Prova ad aumentarlo per più di 10 secondi. Un'altra opzione sarebbe quella di verificare un altro caso nell'iframe. Non ho familiarità con il sito che stai testando, quindi non posso aiutarti ulteriormente. – imiric

+0

Sono arrivato qui perché "Un risultato positivo è per il tipo ExpectedCondition è Boolean restituisce il valore restituito vero o non nullo per tutti gli altri tipi di ExpectedCondition" È scritto in modo orribile e non ha assolutamente senso .... – FoxMulder900

11

Sembra che questo argomento non presenti un esempio di Condizione attesa personalizzata.

In realtà è piuttosto semplice. Prima di tutto, quello che è un Expected Condition in Python selenium bindings:

C'è una grande serie di built-in expected condition classes .

Lavoriamo con l'esempio.Diciamo che vogliamo attendere che il testo di un elemento inizierà con un testo desiderato:

from selenium.webdriver.support import expected_conditions as EC 

class wait_for_text_to_start_with(object): 
    def __init__(self, locator, text_): 
     self.locator = locator 
     self.text = text_ 

    def __call__(self, driver): 
     try: 
      element_text = EC._find_element(driver, self.locator).text 
      return element_text.startswith(self.text) 
     except StaleElementReferenceException: 
      return False 

Usage:

WebDriverWait(driver, 10).until(wait_for_text_to_start_with((By.ID, 'myid'), "Hello, World!")) 
1

Utilizzando la tecnica descritta da @alecxe, ma leggermente modificato per far fronte alla expected_conditions che accettano un elemento invece di un localizzatore : (In questo caso, poiché non v'è alcuna selenium.webdriver.support.expected_conditions.invisibility_of(element), sto aspettando il metodo is_displayed() per falso segnale)

class wait_for_element_to_be_invisible(object): 
    def __init__(self, element): 
     self.element = element 

    def __call__(self, driver): 
     return not(self.element.is_displayed()) 

def test_collapsible_blocks_expand_or_collapse(self): 
    self.browser.get(self.server_url+'/courses/1/') 
    shadables = self.browser.find_elements_by_class_name('shade') 
    for shadable in shadables: 
     ## parent, then sibling element (*) 
     shady_bit = shadable.find_element_by_xpath('../following-sibling::*') 
     element = WebDriverWait(self.browser, 10).until(
      EC.visibility_of(shady_bit)) 
     shadable.click() 
     element = WebDriverWait(self.browser, 10).until(
      self.wait_for_element_to_be_invisible(shady_bit)) 

Il frammento HTML con i bit rilevanti del DOM è:

<h4 class="shadable"><span class="shade" title="Show/Hide">↓</span> 
    <a href="/link/to/uri">Title of Section</a> 
</h4> 
<article class="abstract"> 
    <p>Descriptive part which is shadable 
    </p> 
</article>` 
Problemi correlati