StaleElementException al iterar con Python

Resuelto Mariah Akinbi asked hace 6 años • 0 respuestas

Estoy intentando crear un raspador web básico para los resultados de Amazon. Mientras repito los resultados, a veces llego a la página 5 (a veces solo a la página 2) de los resultados y luego StaleElementExceptionaparece un. Cuando miro el navegador después de que se lanza la excepción, puedo ver que el controlador/página no se desplazó hacia abajo hasta donde están los números de página (barra inferior).

Mi código:

driver.get('https://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=sonicare+toothbrush')

for page in range(1,last_page_number +1):

    driver.implicitly_wait(10)

    bottom_bar = driver.find_element_by_class_name('pagnCur')
    driver.execute_script("arguments[0].scrollIntoView(true);", bottom_bar)

    current_page_number = int(driver.find_element_by_class_name('pagnCur').text)

    if page == current_page_number:
        next_page = driver.find_element_by_xpath('//div[@id="pagn"]/span[@class="pagnLink"]/a[text()="{0}"]'.format(current_page_number+1))
        next_page.click()
        print('page #',page,': going to next page')
    else:
        print('page #: ', page,'error')

Revisé esta pregunta y supongo que se puede aplicar una solución similar, pero no estoy seguro de cómo encontrar algo en la página que desaparece. Además, en función de la rapidez con la que se imprimen las declaraciones, puedo ver que implicitly_wait(10)en realidad no está esperando 10 segundos completos.

La excepción apunta a la línea que comienza con "driver.execute_script". Esta es la excepción:

StaleElementReferenceException: Message: The element reference of <span class="pagnCur"> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed

A veces obtengo un ValueError:

ValueError: invalid literal for int() with base 10: ''

Entonces, estos errores/excepciones me llevan a creer que algo sucede al esperar a que la página se actualice por completo.

Mariah Akinbi avatar Dec 06 '18 04:12 Mariah Akinbi
Aceptado

Si solo desea que su secuencia de comandos repita todas las páginas de resultados, no necesita ninguna lógica complicada; simplemente haga clic en el botón Siguiente mientras sea posible:

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.common.exceptions import TimeoutException

driver = webdriver.Chrome()

driver.get('https://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=sonicare+toothbrush')

while True:
    try:
        wait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a > span#pagnNextString'))).click()
    except TimeoutException:
        break

PD: también tenga en cuenta que implicitly_wait(10)no debe esperar 10 segundos completos , sino esperar hasta 10 segundos para que el elemento aparezca en HTML DOM . Entonces, si el elemento se encuentra dentro de 1 o 2 segundos, entonces la espera ha terminado y no esperará a descansar de 8 a 9 segundos...

Andersson avatar Dec 05 '2018 22:12 Andersson

Este mensaje de error...

StaleElementReferenceException: Message: The element reference of <span class="pagnCur"> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed

...implica que la referencia anterior del elemento ahora está obsoleta y la referencia del elemento ya no está presente en el DOM de la página.

Las razones comunes detrás de este problema son:

  • El elemento ha cambiado de posición dentro del HTML.
  • El elemento ya no está adjunto al ÁRBOL DOM.
  • Se ha actualizado la página web en la que formaba parte el elemento.
  • La instancia anterior del elemento ha sido actualizada por JavaScript o AjaxCall .

Este caso de uso

Manteniendo su concepto de desplazarsescrollIntoView() e imprimir un par de mensajes de depuración útiles, hice algunos ajustes menores que inducen WebDriverWait y puede usar la siguiente solución :

  • Bloque de código:

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    options = Options()
    options.add_argument("start-maximized")
    options.add_argument('disable-infobars')
    options.add_argument("--disable-extensions")
    driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("https://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=sonicare+toothbrush")
    while True:
        try:
            current_page_number_element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "span.pagnCur")))
            driver.execute_script("arguments[0].scrollIntoView(true);", current_page_number_element)
            current_page_number = current_page_number_element.get_attribute("innerHTML")
            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.pagnNextArrow"))).click()
            print("page # {} : going to next page".format(current_page_number))
        except:
            print("page # {} : error, no more pages".format(current_page_number))
            break
    driver.quit()
    
  • Salida de consola:

    page # 1 : going to next page
    page # 2 : going to next page
    page # 3 : going to next page
    page # 4 : going to next page
    page # 5 : going to next page
    page # 6 : going to next page
    page # 7 : going to next page
    page # 8 : going to next page
    page # 9 : going to next page
    page # 10 : going to next page
    page # 11 : going to next page
    page # 12 : going to next page
    page # 13 : going to next page
    page # 14 : going to next page
    page # 15 : going to next page
    page # 16 : going to next page
    page # 17 : going to next page
    page # 18 : going to next page
    page # 19 : going to next page
    page # 20 : error, no more pages
    
undetected Selenium avatar Dec 06 '2018 06:12 undetected Selenium