switch_to - Espere hasta que la página se cargue con Selenium WebDriver para Python
wait for selenium python (9)
¿Has probado
driver.implicitly_wait
?
Es como una configuración para el controlador, por lo que solo se 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 que se dé por vencido. He usado esto en escenarios similares de desplazamiento hacia abajo, así que no veo por qué no funcionaría en su caso. Espero que esto sea útil.
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, necesito 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.
¿Qué hay de poner WebDriverWait en el ciclo While y capturar las excepciones?
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
browser = webdriver.Firefox()
browser.get("url")
delay = 3 # seconds
while True:
try:
WebDriverWait(browser, delay).until(EC.presence_of_element_located(browser.find_element_by_id(''IdOfMyElement'')))
print "Page is ready!"
break # it will break from the loop once the specific element will be present.
except TimeoutException:
print "Loading took too much time!-Try again"
Aquí lo hice usando una forma bastante simple:
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("url")
searchTxt=''''
while not searchTxt:
try:
searchTxt=browser.find_element_by_name(''NAME OF ELEMENT'')
searchTxt.send_keys("USERNAME")
except:continue
Como se menciona en la respuesta de David Cullen , siempre he recomendado usar una línea como la siguiente:
element_present = EC.presence_of_element_located((By.ID, ''element_id''))
WebDriverWait(driver, timeout).until(element_present)
Fue difícil para mí encontrar en cualquier lugar todos los localizadores posibles que se puedan usar con la sintaxis
By
, por lo que pensé que sería útil proporcionar aquí la lista.
Según
Web Scraping with Python
por Ryan Mitchell:
ID
Usado en el ejemplo; encuentra elementos por su atributo de identificación HTML
CLASS_NAME
Se usa para buscar elementos por su atributo de clase HTML. ¿Por qué esta función
CLASS_NAME
no es simplementeCLASS
? Usar el formularioobject.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, se usóCLASS_NAME
su lugar.
CSS_SELECTOR
Encuentre elementos por su clase, id o nombre de etiqueta, usando la
#idName
,.className
,tagName
.
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_TEXT
, pero coincide en una cadena parcial.
NAME
Encuentra etiquetas HTML por su atributo de nombre. Esto es útil para formularios HTML.
TAG_NAME
Ajusta las etiquetas HTML por su nombre de etiqueta.
XPATH
Utiliza una expresión XPath ... para seleccionar elementos coincidentes.
Desde selenium/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"))
El
webdriver
esperará a que se cargue una página de forma predeterminada mediante el método
.get()
.
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 verificar alertas. Puede usar cualquier otro tipo de método para encontrar el localizador.
EDITAR 1:
Debo mencionar que el
webdriver
esperará a que se cargue una página de forma predeterminada.
No espera la carga dentro de los marcos o las solicitudes de ajax.
Significa que cuando usa
.get(''url'')
, su navegador esperará hasta que la página esté completamente cargada y luego vaya al siguiente comando en el código.
Pero cuando publica una solicitud ajax,
webdriver
no espera y es su responsabilidad esperar un tiempo apropiado para que se cargue la página o una parte de la página;
Por lo tanto, hay un módulo llamado
expected_conditions
.
En una nota al margen, en lugar de desplazarse hacia abajo 100 veces, puede verificar si no hay más modificaciones en el DOM (en el caso de que la parte inferior de la página esté cargada de manera lenta 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
Encuentra a continuación 3 métodos:
readyState
Página de comprobación 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''
La función
wait_for
helper es buena, pero desafortunadamenteclick_through_to_new_page
está abierta 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, ypage_has_loaded
simplemente vuelve a ser cierto de inmediato.
id
Comparando nuevos identificadores de página con el 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 identificadores no sea tan efectivo como esperar excepciones de referencia obsoletas.
staleness_of
Usando el método
staleness_of
:
@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 .
Intentar pasar
find_element_by_id
al constructor para
presence_of_element_located
(como se muestra en la
respuesta aceptada
) provocó que se
NoSuchElementException
.
Tuve que usar la sintaxis en el
comment
los
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 documentation . Aquí hay un enlace a la documentación de By .