1. Análisis de rendimiento
¿Por qué es necesaria la optimización?
Imagina un coche potente, capaz de acelerar de 0 a 100 km/h en tres segundos, pero que consume gasolina como una ballena come plancton. Pues tu script podría ser muy rápido, pero extremadamente "glotón", hablando de recursos y tiempo de ejecución. Además, las "fugas" de recursos podrían hacerlo inestable, lo que a su vez podría llevar a errores. La optimización ayuda a evitar estos problemas.
Primero que nada, como dicen los cirujanos, hacemos un "corte". Realizaremos un análisis del rendimiento de nuestro script para entender dónde podría estar "sufriendo".
Métodos para verificar la velocidad y estabilidad de ejecución del script
Una forma sencilla de analizar es usar herramientas básicas de Python, como el módulo time. Vamos a añadir algunas líneas de código a nuestro script para entender qué operaciones llevan más tiempo.
import time
start_time = time.time()
# Aquí tu código para realizar acciones con Selenium
end_time = time.time()
print(f"Tiempo de ejecución: {end_time - start_time} segundos")
Este pequeño fragmento de código te ayudará a determinar cuánto tiempo lleva ejecutar una parte del código. Con estos "temporizadores" puedes localizar los "cuellos de botella".
Identificación de puntos débiles y su optimización
Una vez que encuentres la parte del código que "consume" más tiempo, puedes tomar medidas. Tal vez estás accediendo a elementos dinámicos más de lo necesario, o tu código se ha convertido en un "spaghetti". El primer paso es identificar, el segundo es actuar.
Reducir el número de solicitudes: Verifica si estás realizando demasiadas transiciones innecesarias entre páginas o actualizaciones del DOM. Por ejemplo, el uso del método WebDriverWait ayuda a ejecutar el script solo después de que los elementos deseados estén completamente cargados.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'myDynamicElement'))
)
Caché de datos: Si trabajas con los mismos datos repetidamente, considera usar caché. Guarda los datos en variables o en el caché para minimizar las operaciones que consumen muchos recursos.
2. Mejora de la estructura del script
Si tu código es legible como un mapa del metro sin indicadores ni nombres de estaciones, es hora de mejorarlo. Una estructura óptima del código es la clave para un fácil entendimiento y, en consecuencia, menos errores.
Uso de pipelines de datos y decisiones algorítmicas óptimas
Piensa en estructurar tu código en forma de pipelines, donde cada función o módulo se encargue de una parte específica de la lógica. Dividir el código en bloques lógicos no solo mejora la legibilidad, sino que también facilita la depuración.
def load_page(url):
driver.get(url)
def extract_data():
# Código para extraer datos
pass
def save_data():
# Código para guardar datos
pass
load_page("http://example.com")
extract_data()
save_data()
Mejorar la legibilidad y testabilidad del código
Sigue el principio de "una función, una tarea". Esto facilitará las pruebas y el refactorizado. Usa constantes con nombres en lugar de usar "números mágicos" y cadenas para mayor claridad.
MAX_RETRIES = 5
def fetch_data_with_retry():
for attempt in range(MAX_RETRIES):
try:
# Intento de solicitud de datos
pass
except Exception as e:
print(f"Intento {attempt+1} fallido: {e}")
3. Si el código se puede mejorar, se debe mejorar
Usa esperas explícitas en lugar de implícitas
Las esperas explícitas permiten un control preciso, haciendo que Selenium comience a ejecutar acciones al esperar a que los elementos necesarios estén presentes. En lugar de confiar en esperas implícitas (por ejemplo, implicitly_wait), usa la biblioteca WebDriverWait, que permite configurar las esperas para elementos específicos en función de condiciones (por ejemplo, el elemento es visible, está listo para hacer clic, etc.).
Ejemplo de uso de espera explícita
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "target_element"))
)
Asegúrate de la disponibilidad de la página
Después de cargar la página, no siempre todos los elementos están disponibles de inmediato, especialmente si el sitio usa métodos de carga asincrónicos (AJAX). Usa document.readyState para verificar la carga completa del documento antes de comenzar la interacción.
Ejemplo de verificación de carga completa de la página
def wait_for_page_load(driver):
WebDriverWait(driver, 10).until(
lambda d: d.execute_script("return document.readyState") == "complete"
)
Minimiza el uso de time.sleep
El método time.sleep() hace que el script espere un tiempo fijo y ralentiza su trabajo, especialmente con retrasos largos. En su lugar, usa WebDriverWait, que es más flexible y termina la espera tan pronto como se cumple la condición deseada.
Usa rutas resistentes a elementos
Los localizadores frágiles, como rutas XPath que dependen de estructuras HTML específicas, pueden dejar de funcionar rápidamente si la estructura del sitio cambia. Para evitar esto, intenta usar localizadores más resistentes, como los atributos id, name, class y data-*, que son más estables.
Ejemplo de uso confiable de atributos
# Usamos id para buscar, si está disponible
element = driver.find_element(By.ID, "submit_button")
# Si no hay id, podemos usar atributo data-* o clases únicas
element = driver.find_element(By.CSS_SELECTOR, "[data-role='main-button']")
GO TO FULL VERSION