3
votes

Python Selenium: attendre qu'un élément OU un autre élément se charge

J'utilise ce code pour attendre le chargement d'un élément:

browser = webdriver.Chrome(executable_path=chromedriver,options=ChromeOpts, desired_capabilities=captain) 
wait = WebDriverWait(browser, 5)
openbrowser = browser.get(url) 
wait.until(EC.presence_of_element_located((By.ID, 'h1')))
browser.execute_script("window.stop();")

Cependant, ce dont j'ai vraiment besoin est d'attendre un élément OU un autre. Ainsi je peux, par exemple, attendre «h1» OU «rf-footer».

merci,


0 commentaires

3 Réponses :


0
votes

Vous pouvez le faire en utilisant expected_conditions

from selenium.webdriver.support import expected_conditions

la solution complète peut être trouvée ici: Selenium Expected Conditions - possible d'utiliser 'ou'?


1 commentaires

Merci! Je l'ai acheté en utilisant TRY / EXCEPT. openbrowser = browser.get (url) #navigate to the page try: wait.until (EC.presence_of_element_located ((By.ID, id_stop))) sauf: wait.until (EC.presence_of_element_located ((By.ID, 'rf-footer'))) browser.execute_script ("window.stop ();")



-1
votes

Je l'ai acheté en utilisant TRY / EXCEPT.

openbrowser = browser.get(url) #navigate to the page 
try: 
   wait.until(EC.presence_of_element_located((By.ID, id_stop))) 
except: 
   wait.until(EC.presence_of_element_located((By.ID, 'rf-footer')))
browser.execute_script("window.stop();")


0 commentaires

3
votes

Vous pouvez combiner les deux vérifications en une seule opération wait () - en utilisant une expression lambda de python, en utilisant les méthodes find_elements _ * () collées avec un ou :

element = wait.until(lambda x: x.find_elements_by_id("id1") or x.find_elements_by_css_selector("#id2"))[0]

Vous pouvez utiliser cette approche même pour obtenir l'élément correspondant en premier - le [0] à la fin. Cette solution fonctionne, car find_elements _ * () renvoie une liste de tous les éléments correspondants, ou une liste vide s'il n'y en a pas (un booléen faux). Donc, si le premier appel ne trouve rien, le second est évalué; qui se répète jusqu'à ce que l'un d'eux trouve une correspondance ou que le temps s'écoule.

Cette approche donne l'avantage que wait.until () s'arrêtera immédiatement après l'une des deux passes - par exemple la vitesse.


Par rapport à un bloc try-catch - dans celui-ci, la première condition doit échouer (attendre jusqu'à X secondes, généralement 10), pour que la seconde soit même vérifiée; donc si le premier est faux, tandis que le second est vrai - le temps d'exécution / attente sera d'au moins X secondes plus le temps que prendra la deuxième vérification.
Dans le pire des cas, lorsque les deux sont faux, vous attendez 2X, contre X pour combiner les deux. Si vous ajoutez d'autres conditions, vous ne faites qu'augmenter le facteur.


10 commentaires

Merci!! J'ai essayé le premier et j'ai obtenu que: AttributeError: l'objet 'WebDriver' n'a pas d'attribut 'presence_of_element_located'


Des idées pour le résoudre?


Mon mauvais, gros doigts il sur mobile (de même maintenant, les doigts croisés :). Le problème était que presence_of_element_located () est une classe dans expected_conditions , pas une méthode de l'objet webdriver (qui est le x dans le lambda).


Maintenant, il se produit une autre exception. Après avoir exécuté: browser.execute_script ("return document.documentElement.outerHTML") j'obtiens: selenium.common.exceptions.WebDriverException: Message: erreur inconnue: Impossible de lire la propriété 'externalHTML' de null Alors que j'essaie d'obtenir le HTML, il semble qu'il renvoie null.


Mon code: browser = webdriver.Chrome (executable_path = chromedriver, options = ChromeOpts, desire_capabilities = capa) wait = WebDriverWait (navigateur, 10) openbrowser = browser.get (url) #navigate vers la page a = wait.until (lambda x: EC.presence_of_element_located ((By.ID, "id_max")) ou EC.presence_of_element_located ((By.ID, "max_id"))) browser.execute_script ("window.stop ();") html = browser .execute_script ("return document.documentElement.outerHTML") BTW, déjà changé en innerHTML. Je vois sur la console qu'avant que la page cesse de se charger, la console est déjà finalisée pour exécuter le code.


Je pense que je l'ai compris, j'ai placé un time.sleep (x) avant d'exécuter le dernier script.


La pièce avec conditions_attendues est incorrecte, car ec.presence_of_element_located renvoie un objet et donc l'utilisation de l'opérateur ou retournera toujours la pièce avant ou mais la partie après ou ne sera jamais exécutée.


@ JakubBláha vous avez raison, cela ne fera pas l'affaire - mais pour une raison différente. Le premier presence_of_element_located () quand l'élément n'est pas là ne retournera pas d'objet, mais lèvera une exception - qui est interceptée par wait.until () , et le le cycle est répété. Ainsi, le deuxième presence_of_element_located () ne sera en fait jamais exécuté - c'est la partie sur laquelle vous avez raison. Je vais éditer la réponse, en ne gardant que les find_elements * () - cela fonctionnera toujours comme s'il n'y avait aucun trouvé, ils retournent une liste vide (booléen false).


Quelle exception soulèverait-il cependant? Il ne fait rien tant qu'il n'est pas appelé par la méthode until , donc il ne peut pas déclencher d'exception. Le deuxième objet n'a même jamais été instancié. Merci d'avoir édité la réponse et merci de fournir une solution de travail réelle.


Il lève ElementNotFound, qui est géré par le bloc catch de jusqu'à () .