2012-03-05 16 views
35

Ho un problema: sto utilizzando il driver del selenio (firefox) per aprire una pagina Web, fare clic su alcuni collegamenti ecc. Quindi acquisire uno screenshot.Python - Selenium WebDriver - Esiste l'elemento di controllo

Il mio script funziona correttamente dalla CLI, ma quando viene eseguito tramite un cronjob non supera il primo test find_element(). Devo aggiungere un po 'di debug o qualcosa che mi aiuti a capire perché non funziona.

Fondamentalmente, devo fare clic su un'ancora di "accesso" prima di andare alla pagina di accesso. Il costrutto dell'elemento è:

<a class="lnk" rel="nofollow" href="/login.jsp?destination=/secure/Dash.jspa">log in</a> 

Sto usando il find_element Con il metodo LINK_TEXT:

login = driver.find_element(By.LINK_TEXT, "log in").click() 

Io sono un po 'di Python Noob, quindi sono in lotta con la lingua un po' ..

A) Come si verifica che il collegamento venga effettivamente rilevato da python? Dovrei usare try/catch block?

B) Esiste un modo migliore/più affidabile per individuare l'elemento DOM rispetto a LINK_TEXT? Per esempio. In JQuery, puoi usare un selettore più specifico $ ('a.lnk: contains (log in)'). Do_something();

Ho risolto il problema principale ed era solo un problema con le dita - stavo chiamando lo script con parametri errati - Semplice errore.

Mi piacerebbe ancora qualche indicazione su come verificare se esiste un elemento. Inoltre, un esempio/spiegazione di Wake impliciti/espliciti invece di utilizzare una chiamata time.leep() scadente.

Cheers, ns

+0

È anche possibile trovare elementi in base al localizzatore CSS o xpath. Tende ad essere meno fragile rispetto al contenuto del testo. –

+0

Credo che entrambi - utilizzando il testo del contenuto e XPATH/CSS - siano fragili a piccoli cambiamenti nel design piuttosto che nella logica dell'applicazione. Un modo migliore sarebbe trovare l'elemento con 'id',' class_name' o 'name'. –

risposta

34

A) Sì. Il modo più semplice per verificare se esiste un elemento è semplicemente chiamare find_element all'interno di uno try/catch.

B) Sì, cerco sempre di identificare gli elementi senza utilizzare il loro testo per 2 motivi:

  1. il testo è più propensi a cambiare e;
  2. se è importante per te, non sarai in grado di eseguire i test contro build localizzati.

soluzione sia:

  1. È possibile utilizzare XPath per trovare un elemento padre o antenato che ha un ID o un altro identificatore univoco e poi trovare è figlio/discendente che corrisponde o;
  2. è possibile richiedere un ID o nome o qualche altro identificativo univoco per il collegamento stesso.

Per le domande di follow-up, utilizzando try/catch è come si può dire se un elemento esiste o no e buoni esempi di attesa può essere trovato qui: http://seleniumhq.org/docs/04_webdriver_advanced.html

+0

Un uso che ho per trovare il testo è vedere se viene visualizzato un messaggio flash riuscito/non riuscito. Non sono sicuro se c'è un modo migliore per farlo? –

+0

Questi sono assolutamente ottimi motivi per evitare di selezionare tramite il testo – kevlarr

56

una)

from selenium.common.exceptions import NoSuchElementException   
def check_exists_by_xpath(xpath): 
    try: 
     webdriver.find_element_by_xpath(xpath) 
    except NoSuchElementException: 
     return False 
    return True 

b) usa xpath - il più affidabile. Inoltre è possibile utilizzare xpath come standard in tutti gli script e creare funzioni come quelle sopra menzionate per uso universale.

UPDATE: Ho scritto la risposta iniziale oltre 4 anni fa e al momento ho pensato che xpath sarebbe stata l'opzione migliore. Ora consiglio di utilizzare i selettori di cv . Raccomando ancora di non mescolare/utilizzare "per id", "per nome", ecc. E utilizzare invece un solo approccio.

+0

Dovresti anche passare oggetto: browser = webdriver.Firefox() alla tua funzione personalizzata – 8090PZ

+0

In generale, raramente ho trovato pagine html conformi all'idea di uniforming matching. C'è un modo per aggirare le combinazioni di combinazioni dei metodi di localizzazione su tali pagine? –

+0

@KshitijSaraogi Non capisci completamente la tua domanda. Se rimani, è impossibile avere solo "selettori di css" nei tuoi test di webdriver - in realtà è possibile. L'ho fatto solo negli ultimi 6 anni. –

22

Nessuna delle soluzioni fornite mi è sembrata più facile, quindi mi piacerebbe aggiungere la mia strada.

In sostanza, si ottiene l'elenco degli elementi anziché solo l'elemento e quindi si contano i risultati; se è zero, allora non esiste. Esempio:

if driver.find_elements_by_css_selector('#element'): 
    print "Element exists" 

Avviso la "s" in find_elements_by_css_selector per assicurarsi che può essere numerabile.

EDIT: stavo controllando la len( della lista, ma di recente ho appreso che una lista vuota è Falsey, quindi non è necessario per ottenere la lunghezza della lista a tutti, lasciando per il codice ancora più semplice.

Inoltre, un'altra risposta dice che l'uso di xpath è più affidabile, il che non è vero. Vedi What is the difference between css-selector & Xpath? which is better(according to performance & for cross browser testing)?

+2

È più veloce del precedente metodo di gestione delle eccezioni? –

+1

@GalBracha Buona domanda, presumo che probabilmente dipenderà dalla versione e dalla piattaforma, quindi se la differenza di velocità è così importante per te qui, ti consiglio di testarla sulla tua piattaforma di destinazione per ottenere i migliori risultati. Tuttavia, qui va fatto un punto sulle pre-ottimizzazioni e la leggibilità del codice potrebbe essere più importante del miglioramento delle prestazioni trascurabile in questo caso –

Problemi correlati