web-dev-qa-db-fra.com

Python - Selenium WebDriver - L'élément de contrôle existe

J'ai un problème - j'utilise le pilote Web Selenium (firefox) pour ouvrir une page Web, cliquez sur quelques liens, etc., puis faites une capture d'écran.

Mon script fonctionne correctement à partir de la CLI, mais lorsqu'il est exécuté via un cronjob, il ne dépasse pas le premier test find_element (). J'ai besoin d'ajouter un débogage, ou quelque chose pour m'aider à comprendre pourquoi il échoue.

Fondamentalement, je dois cliquer sur une ancre de "connexion" avant de me rendre à la page de connexion. La construction de l'élément est:

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

J'utilise la méthode find_element By LINK_TEXT:

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

Je suis un peu un Python Noob, alors je me bats un peu avec la langue ...

A) Comment puis-je vérifier que le lien est effectivement capté par Python? Devrais-je utiliser try/catch block?

B) Existe-t-il un moyen meilleur/plus fiable de localiser l'élément DOM que par LINK_TEXT? Par exemple. Dans JQuery, vous pouvez utiliser un sélecteur plus spécifique, $ ('a.lnk: contient (se connecter)'). Do_something ();


J'ai résolu le problème principal et c'était juste un problème de doigt - J'appelais le script avec des paramètres incorrects - Simple erreur.

Je voudrais quand même des indications sur la manière de vérifier si un élément existe. En outre, un exemple/explication de Waits implicite/explicite au lieu d’utiliser un appel crappy time.sleep (). 

À la vôtre, ns

43
nonshatter

A) oui Le moyen le plus simple de vérifier l’existence d’un élément consiste à appeler simplement find_element dans un try/catch.

B) Oui, j'essaie toujours d'identifier des éléments sans utiliser leur texte pour deux raisons: 

  1. le texte est plus susceptible de changer et;
  2. si cela est important pour vous, vous ne pourrez pas exécuter vos tests sur des versions localisées.

solution soit:

  1. Vous pouvez utiliser xpath pour rechercher un élément parent ou ancêtre ayant un ID ou un autre identifiant unique, puis trouver son enfant/descendant correspondant
  2. vous pouvez demander un identifiant, un nom ou un autre identifiant unique pour le lien lui-même.

Pour les questions suivantes, utilisez try/catch pour savoir si un élément existe ou non, et de bons exemples d’attente peuvent être trouvés ici: http://seleniumhq.org/docs/04_webdriver_advanced.html

40
Sam Woods

une)

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) utilisez xpath - le plus fiable. De plus, vous pouvez prendre le xpath en tant que norme dans tous vos scripts et créer les fonctions décrites ci-dessus pour une utilisation universelle.

UPDATE: J'ai écrit la réponse initiale il y a plus de 4 ans et, à l'époque, je pensais que xpath serait la meilleure option. Maintenant, je recommande d’utiliser les sélecteurs css . Je recommande toujours de ne pas mélanger/utiliser "par identifiant", "par nom", etc., et d’utiliser une seule approche à la place.

68
Alex Okrushko

Aucune des solutions fournies ne m'a semblé la plus facile, alors j'aimerais ajouter ma propre manière.

Fondamentalement, vous obtenez la liste des éléments au lieu de simplement l'élément, puis vous comptez les résultats; si c'est zéro, alors ça n'existe pas. Exemple: 

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

Notez le "s" dans find_elements_by_css_selector pour vous assurer qu'il peut être comptabilisé.

EDIT: Je vérifiais le len( de la liste, mais j'ai récemment appris qu'une liste vide est falsey. Vous n'avez donc pas besoin de connaître la longueur de la liste, ce qui vous laisse un code encore plus simple. 

En outre, une autre réponse indique que l'utilisation de xpath est plus fiable, ce qui n'est tout simplement pas vrai. Voir Quelle est la différence entre css-selector et Xpath? quel est le meilleur (en fonction des performances et des tests sur plusieurs navigateurs)?

37
Brian Leishman

Solution sans try & catch et sans nouvelles importations:

if len(driver.find_elements_by_id('blah')) > 0: #pay attention: find_element*s*
    driver.find_element_by_id('blah').click #pay attention: find_element
2
Super Mario

Identique à Brian, mais ajoutez à cette réponse de tstempko:

https://sqa.stackexchange.com/questions/3481/quicker-way-to-assert-that-an-element-does-not-exist

Alors j'ai essayé et ça marche vite:

driver.implicitly_wait(0)

if driver.find_element_by_id("show_reflist"):        
 driver.find_element_by_id("show_reflist").find_element_by_tag_name("img").click()

après cela, je restaure ma valeur par défaut

driver.implicitly_wait(30)
1
vmk

driver.find_element_by_id("some_id").size() est une méthode de classe.

Ce dont nous avons besoin, c'est: 

driver.find_element_by_id("some_id").size qui est un dictionnaire pour:

if driver.find_element_by_id("some_id").size['width'] != 0 : print 'button exist'

0
Lopi Dani

Vous pouvez également le faire de manière plus concise en utilisant

driver.find_element_by_id("some_id").size() != 0
0
Rohith R Nair