Espere hasta que la página se cargue con Selenium WebDriver para Python

9 minutos de lectura

Espere hasta que la pagina se cargue con Selenium WebDriver
apogne

Quiero raspar todos los datos de una página implementada por un desplazamiento infinito. El siguiente código de Python funciona.

for i in range(100):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(5)

Esto significa que cada vez que me desplazo hacia abajo, debo esperar 5 segundos, lo que generalmente es suficiente para que la página termine de cargar los contenidos recién generados. Pero, esto puede no ser eficiente en el tiempo. La página puede terminar de cargar los nuevos contenidos en 5 segundos. ¿Cómo puedo detectar si la página terminó de cargar los nuevos contenidos cada vez que me desplazo hacia abajo? Si puedo detectar esto, puedo desplazarme hacia abajo nuevamente para ver más contenido una vez que sepa que la página terminó de cargarse. Esto es más eficiente en el tiempo.

  • Puede ser útil saber un poco más sobre la página. ¿Los elementos son secuenciales o predecibles? Puede esperar a que se carguen los elementos comprobando la visibilidad con id o xpath

    – usuario2272115

    25/10/2014 a las 20:32


  • Estoy rastreando la siguiente página: pinterest.com/cremedelacrumb/yum

    – apogne

    25/10/2014 a las 22:18


  • posible duplicado de Detectar de forma fiable la carga de la página o el tiempo de espera, Selenium 2

    – kenorb

    21 mayo 2015 a las 23:10

  • ¿Responde esto a tu pregunta? Espere a que se cargue la página en Selenium

    – Matej J.

    13 de julio de 2020 a las 19:17

Espere hasta que la pagina se cargue con Selenium WebDriver
Zeinab Abbasimazar

los webdriver esperará a que se cargue una página de forma predeterminada a través de .get() método.

Como puede estar buscando algún elemento específico como dijo @ user227215, debe usar WebDriverWait para esperar un elemento ubicado en su página:

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

browser = webdriver.Firefox()
browser.get("url")
delay = 3 # seconds
try:
    myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'IdOfMyElement')))
    print "Page is ready!"
except TimeoutException:
    print "Loading took too much time!"

Lo he usado para comprobar alertas. Puede utilizar cualquier otro método de tipo para encontrar el localizador.

EDITAR 1:

Debo mencionar que el webdriver esperará a que se cargue una página de forma predeterminada. No espera a que se cargue dentro de los marcos ni a las solicitudes de ajax. Significa cuando usas .get('url'), su navegador esperará hasta que la página esté completamente cargada y luego pasará al siguiente comando en el código. Pero cuando publicas una solicitud ajax, webdriver no espera y es su responsabilidad esperar una cantidad adecuada de tiempo para que se cargue la página o una parte de la página; entonces hay un módulo llamado expected_conditions.

  • Obtuve el argumento “find_element() después de que * debe ser una secuencia, no WebElement” cambiado a “WebDriverWait(navegador, retraso).hasta(EC.presence_of_element_located((By.ID, “IdOfMyElement”))) ” ver manual selenium-python.readthedocs.org/en/latest/waits.html

    – Fragmentos

    11 de septiembre de 2015 a las 9:29

  • El comentario de @fragles y la respuesta de David Cullen fueron lo que funcionó para mí. ¿Quizás esta respuesta aceptada podría actualizarse en consecuencia?

    -Michael Ohlrogge

    20 mayo 2016 a las 19:13

  • Paso browser.find_element_by_id('IdOfMyElement') provoca un NoSuchElementException ser criado. los documentación dice que pase una tupla que se ve así: (By.ID, 'IdOfMyElement'). ver mi respuesta

    –David Cullen

    6 de junio de 2016 a las 12:52


  • Espero que esto ayude a alguien más porque inicialmente no estaba claro para mí: WebDriverWait en realidad devolverá un objeto web en el que luego puede realizar una acción (por ejemplo, click()), leer texto de etc. Tenía la impresión errónea de que solo causaba una espera, después de lo cual aún tenía que encontrar el elemento. Si hace una espera, luego un elemento de búsqueda posterior, el selenio generará un error porque intenta encontrar el elemento mientras la espera anterior aún se está procesando (con suerte, eso tiene sentido). La conclusión es que no necesita encontrar el elemento después de usar WebDriverWait, ya es un objeto.

    – BenWilson

    1 de diciembre de 2016 a las 22:52


  • @Gopgop Vaya esto es tan feo no es un comentario constructivo. ¿Qué tiene de feo? ¿Cómo podría mejorarse?

    – Modo Tollens

    30 de diciembre de 2018 a las 22:22

Espere hasta que la pagina se cargue con Selenium WebDriver
david cullen

tratando de pasar find_element_by_id al constructor por presence_of_element_located (como se muestra en la respuesta aceptada) causó NoSuchElementException ser criado. Tuve que usar la sintaxis en el comentario de fragles:

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

driver = webdriver.Firefox()
driver.get('url')
timeout = 5
try:
    element_present = EC.presence_of_element_located((By.ID, 'element_id'))
    WebDriverWait(driver, timeout).until(element_present)
except TimeoutException:
    print "Timed out waiting for page to load"

Esto coincide con el ejemplo en la documentación. Aquí hay un enlace a la documentación para Por.

  • ¡Gracias! sí, esto era necesario para mí también. ID no es el único atributo que se puede usar, para obtener una lista completa, use ayuda (Por). Por ejemplo, usé EC.presence_of_element_located((By.XPATH, "//*[@title='Check All Q1']"))

    -Michael Ohlrogge

    20 mayo 2016 a las 19:11

  • Esa es la forma en que funciona para mí también! Escribí una respuesta adicional ampliando los diferentes localizadores que están disponibles con el By objeto.

    – J0ANMM

    14 de octubre de 2016 a las 7:21

  • He publicado una pregunta de seguimiento sobre las expectativas en las que se pueden cargar diferentes páginas y no siempre la misma página: stackoverflow.com/questions/51641546/…

    – Liquidgenio

    01/08/2018 a las 20:10

  • En algunos casos este método no funciona. Por ejemplo, si raspa la página uno y luego obtiene la página dos del mismo sitio web, todos los ID en dos páginas son iguales y .until(element_present) siempre será True.

    – Meysam

    28 de marzo de 2021 a las 19:01

1646959689 512 Espere hasta que la pagina se cargue con Selenium WebDriver
kenorb

Encuentre a continuación 3 métodos:

listoestado

Verificación de la página readyState (no confiable):

def page_has_loaded(self):
    self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))
    page_state = self.driver.execute_script('return document.readyState;')
    return page_state == 'complete'

los wait_for la función auxiliar es buena, pero desafortunadamente click_through_to_new_page está abierto a la condición de carrera en la que logramos ejecutar el script en la página anterior, antes de que el navegador haya comenzado a procesar el clic, y page_has_loaded simplemente devuelve verdadero de inmediato.

id

Comparando ID de página nueva con la anterior:

def page_has_loaded_id(self):
    self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))
    try:
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id
    except NoSuchElementException:
        return False

Es posible que comparar ID no sea tan efectivo como esperar excepciones de referencia obsoletas.

staleness_of

Utilizando staleness_of método:

@contextlib.contextmanager
def wait_for_page_load(self, timeout=10):
    self.log.debug("Waiting for page to load at {}.".format(self.driver.current_url))
    old_page = self.find_element_by_tag_name('html')
    yield
    WebDriverWait(self, timeout).until(staleness_of(old_page))

Para más detalles, consulte el blog de harry.

  • Por qué dices eso self.driver.execute_script('return document.readyState;') ¿no fiable? Parece funcionar perfectamente para mi caso de uso, que está esperando que se cargue un archivo estático en una nueva pestaña (que se abre mediante javascript en otra pestaña en lugar de .get()).

    – Arthur Hebert-Ryan

    02/04/2018 a las 23:00

  • @ArthurHebert Podría no ser confiable debido a la condición de la carrera, agregué una cita relevante.

    – kenorb

    3 abr 2018 a las 9:40

1646959690 566 Espere hasta que la pagina se cargue con Selenium WebDriver
J0ANMM

Como se menciona en la respuesta de David Cullen, siempre he visto recomendaciones para usar una línea como la siguiente:

element_present = EC.presence_of_element_located((By.ID, 'element_id'))
WebDriverWait(driver, timeout).until(element_present)

Me resultó difícil encontrar en alguna parte todos los posibles localizadores que se pueden usar con el By, por lo que pensé que sería útil proporcionar la lista aquí. De acuerdo a Web Scraping con Python por Ryan Mitchell:

ID

Usado en el ejemplo; encuentra elementos por su atributo de identificación HTML

CLASS_NAME

Se utiliza para buscar elementos por su atributo de clase HTML. ¿Por qué esta función CLASS_NAME no simplemente CLASS? Usando el formulario object.CLASS
crearía problemas para la biblioteca Java de Selenium, donde .class es un método reservado. Para mantener la sintaxis de Selenium consistente entre diferentes idiomas, CLASS_NAME en su lugar.

CSS_SELECTOR

Encuentra elementos por su clase, id o nombre de etiqueta, usando el #idName,
.className, tagName convención.

LINK_TEXT

Encuentra etiquetas HTML por el texto que contienen. Por ejemplo, un enlace que dice “Siguiente” se puede seleccionar usando (By.LINK_TEXT, "Next").

PARTIAL_LINK_TEXT

Similar a LINK_TEXTpero coincide con una cadena parcial.

NAME

Encuentra etiquetas HTML por su atributo de nombre. Esto es útil para formularios HTML.

TAG_NAME

Encuentra etiquetas HTML por su nombre de etiqueta.

XPATH

Utiliza una expresión XPath… para seleccionar elementos coincidentes.

1646959690 945 Espere hasta que la pagina se cargue con Selenium WebDriver
Carlos

Desde selenio/webdriver/support/wait.py

driver = ...
from selenium.webdriver.support.wait import WebDriverWait
element = WebDriverWait(driver, 10).until(
    lambda x: x.find_element_by_id("someId"))

1646959690 61 Espere hasta que la pagina se cargue con Selenium WebDriver
robertspierre

En una nota al margen, en lugar de desplazarse hacia abajo 100 veces, puede verificar si no hay más modificaciones en el DOM (estamos en el caso de que la parte inferior de la página se cargue con AJAX)

def scrollDown(driver, value):
    driver.execute_script("window.scrollBy(0,"+str(value)+")")

# Scroll down the page
def scrollDownAllTheWay(driver):
    old_page = driver.page_source
    while True:
        logging.debug("Scrolling loop")
        for i in range(2):
            scrollDown(driver, 500)
            time.sleep(2)
        new_page = driver.page_source
        if new_page != old_page:
            old_page = new_page
        else:
            break
    return True

1646959691 737 Espere hasta que la pagina se cargue con Selenium WebDriver
ccsinsf

Has probado driver.implicitly_wait. Es como una configuración para el controlador, por lo que solo lo llama una vez en la sesión y básicamente le dice al controlador que espere la cantidad de tiempo dada hasta que se pueda ejecutar cada comando.

driver = webdriver.Chrome()
driver.implicitly_wait(10)

Entonces, si establece un tiempo de espera de 10 segundos, ejecutará el comando lo antes posible, esperando 10 segundos antes de darse por vencido. He usado esto en escenarios de desplazamiento hacia abajo similares, por lo que no veo por qué no funcionaría en su caso. Espero que esto sea útil.

Para poder arreglar esta respuesta, tengo que agregar un nuevo texto. Asegúrese de usar una ‘w’ minúscula en implicitly_wait.

  • ¿Cuál es la diferencia entre espera implícita y espera webdriver?

    – canción0089

    11 de junio de 2020 a las 20:56


  • @song0089 Revisa esto, esto y estas discusiones.

    – selenio no detectado

    9 de agosto de 2020 a las 20:09

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad