Entorno de Trabajo
Sistema operativo: Windows 10
Versión de Python: 3.10
Versión de Selenium: 4.21
- Gestión del WebDriver
Antiguamente, el proceso requería descargar el controlador específico para el navegador y configurar su ruta manualmente:
ruta_chromedriver = r"D:\ubicacion\del\chromedriver" # Reemplazar con la ruta real del controlador
servicio = Service(ruta_chromedriver)
navegador = webdriver.Chrome(service=servicio, opciones=chrome_options)
Actualmente, Selenium ofrece una solución automatizada para descargar y configurar el controlador adecuado:
# Instalar el paquete necesario
pip install webdriver_manager
# Importar el gestor correspondiente al navegador
from webdriver_manager.chrome import ChromeDriverManager
servicio = Service(ChromeDriverManager().install())
navegador = webdriver.Chrome(service=servicio, opciones=chrome_options)
Esta automatización evita problemas cuando el navegador se actualiza y requiere un nuevo controlador.
- Menejo Excepciones en Automatización
Es común usar excepciones para manejar elementos no encontrados:
try:
# Código de navegación
elemento = navegador.find_element(metodo_localizacion, valor_localizacion)
except Exception as e:
# Lógica para cuando no se encuentra el elemento
print("Elemento no encontrado")
El problema con este enfoque es que Expection es demasiado genérico. Es mejor capturar específicamente la excepción NoSuchElementException:
try:
# Código de navegación
elemento = navegador.find_element(metodo_localizacion, valor_localizacion)
except NoSuchElementException as e:
# Lógica específica para elementos no encontrados
print("Elemento no encontrado en la página")
- Elementos No Clickeables
Para verificar si un elemento es clickeable, podemos usar:
# Si no lanza excepción, el elemento es clickeable
elemento = espera.until(EC.element_to_be_clickable((By.METODO, valor)))
En algunos casos, como la navegación en páginas de libros, este método puede no funcionar correctamente:
try:
espera_pagina = WebDriverWait(navegador, 1)
boton_siguiente = espera_pagina.until(EC.element_to_be_clickable((By.XPATH, '//*[@class="next"]')))
registro.info(f'Página: {boton_siguiente}')
elemento_siguiente = navegador.find_element(By.XPATH, '//*[@class="next"]')
elemento_siguiente.click()
except Exception as e:
registro.info("Error al hacer clic en siguiente página")
raise
Una solución es refinar el XPath para apuntar directamente al elemento que falta en la última página:
# En la última página, este elemento no existirá
elemento_siguiente = navegador.find_element(By.XPATH, '//span[@class="next"]/a')
- Texto en Etiquetas Padre
Al obtener el texto de un elemento padre, Selenium incluye el texto de todos sus elementos hijos:
# Ejemplo con la página de Baidu
texto_lista = navegador.find_element(By.ID, "hotsearch-content-wrapper").text
print(texto_lista)
Esto imprimirá tanto el texto del contenedor como el de todos los elementos dentro de él.
- Diferencias entre find_element() y find_elements()
Analizando el código fuente de Selenium, find_element() utiliza internamente find_elements() y toma el primer resultado:
def find_element(self, by=By.ID, value=None):
elementos = self.find_elements(by, value)
if len(elementos) == 0:
raise NoSuchElementException(f"No se encontró elemento con {by}={value}")
return elementos[0]
Por lo tanto, find_element() es equivalente a find_elements()[0], pero con manejo adicional para el caso de no encontrar elementos.