web-dev-qa-db-fra.com

Elément obsolète Python Selenium

Je reçois le message d'erreur suivant lors de l'utilisation de Selenium en python:

Selenium.common.exceptions.StaleElementReferenceException: Message: u'stale element reference: element is not attached to the page document\n

Il est intéressant de noter que l'erreur apparaît à différents moments de la boucle for. Parfois, cela passe par exemple. 4 itérations et autres fois, par exemple. 7.

Certains des codes pertinents en cours d'exécution sont les suivants:

for i in range(0, 22):
    u = driver.find_elements_by_id("data")
    text = u[0].get_attribute("innerHTML")
    driver.find_elements_by_class_name("aclassname")[0].click()

Qu'est-ce que cette erreur signifie et qu'est-ce que je peux essayer de résoudre?

24
bill999

Prise en charge du sélénium Explicit et Implicit Attend. Si vous pensez qu’attendre un certain temps est suffisant pour que votre page soit chargée, utilisez:

driver.implicitly_wait(secs)

mais si vous voulez attendre un événement spécial (par exemple, attendre qu'un élément particulier soit chargé), vous pouvez faire quelque chose comme:

from Selenium.webdriver.support.ui import WebDriverWait
...
...
def find(driver):
    element = driver.find_elements_by_id("data")
    if element:
        return element
    else:
        return False
element = WebDriverWait(driver, secs).until(find)
15
Nima Soroush

Cela signifie que l'élément n'est plus dans le DOM ou qu'il a changé. 

Vous êtes dans une boucle. Pensez à ce qui se passe pendant les itérations: 

  1. quelque chose change lorsque vous cliquez sur l'élément (dernière ligne)
  2. Donc la page change
  3. Vous entrez la prochaine itération. Essayez maintenant de trouver un nouvel élément (votre première ligne dans la boucle).
  4. Vous avez trouvé l'élément
  5. Il finit de changer
  6. Vous essayez de l'utiliser en obtenant un attribut
  7. Bam! L'élément est vieux. Vous l'avez eu à l'étape 4, mais cela a fini de changer à l'étape 5

Le code suivant peut vous aider à trouver l'élément:

from Selenium.common.exceptions import NoSuchElementException
from Selenium.common.exceptions import StaleElementReferenceException
from Selenium.webdriver.common.by import By
from Selenium.webdriver.support.ui import WebDriverWait
from Selenium.webdriver.support import expected_conditions

ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
your_element = WebDriverWait(your_driver, some_timeout,ignored_exceptions=ignored_exceptions)\
                        .until(expected_conditions.presence_of_element_located((By.ID, Your_ID)))
10
Emilio M.

Lorsque la page Web a été rafraîchie ou est passée d'une fenêtre ou d'un formulaire différent à une autre et que vous tentez d'accéder à un élément, l'utilisateur obtiendra l'exception.

Utilisez webdriverwait dans le bloc try --except avec la boucle for: EX:

Code dans lequel j'ai eu staleelementexception:


driver.find_element_by_id(tc.value).click()

driver.find_element_by_xpath ("xpath"). click ()


Réparer :

from Selenium.webdriver.common.by import By
from Selenium.webdriver.support.ui import WebDriverWait
from Selenium.webdriver.support import expected_conditions as EC

driver.find_element_by_id(tc.value).click()
for i in range(4):
   try:
        run_test = WebDriverWait(driver, 120).until( \
        EC.presence_of_element_located((By.XPATH, "xpath")))
        run_test.click()
        break
   except StaleElementReferenceException as e:
        raise e
2
rajkrish06
>>>Stale Exceptions can be handled using **StaleElementReferenceException** to continue to execute the for loop.  

from Selenium.common import exceptions  

# and customize your code of for loop as:  

for i in range(0, 22):  
   try:  
        u = driver.find_elements_by_id("data")  
        text = u[0].get_attribute("innerHTML")  
        driver.find_elements_by_class_name("aclassname")[0].click()  
   except exceptions.StaleElementReferenceException:  
        pass
1
Vishal

Voici la solution python à ce problème: 

def clickAndCatchStaleRefException(locator):



    driver = sel2._current_browser()
    result = False
    attempts = 0

    locator = locator[6:]
    # This line is optional because sometimes you pass a xpath from a varibles file
    # that starts with 'xpath='. This should be omitted otherwise the find_element_by_xpath 
    # function will throw an error.
    # But if you pass an xpath directly you don't need this


    while attempts < 2:
        try:
            driver.find_element_by_xpath(locator).click()
            result = True
            break
        except EC as e:
            raise e
        finally:
            attempts += 1
    return result
0
Rashid