1. Analisi delle prestazioni
A cosa serve l'ottimizzazione?
Immagina una macchina potente che può accelerare fino a 100 km/h in tre secondi, ma che consuma benzina come una balena che mangia plancton. Lo stesso accade con il tuo script, che potrebbe essere molto veloce, ma estremamente "affamato" di risorse e tempo di esecuzione. Inoltre, "perdite" di risorse potrebbero renderlo instabile, portando a errori. L'ottimizzazione ti aiuta a evitare questi problemi.
Per prima cosa, come dicono i chirurghi, facciamo un "taglio". Facciamo un'analisi delle prestazioni del nostro script per capire dove potrebbe "soffrire".
Metodi per controllare velocità e stabilità di esecuzione dello script
Uno dei metodi più semplici di analisi è utilizzare gli strumenti base di Python, come il modulo time
. Aggiungiamo qualche riga al nostro script per capire quali operazioni richiedono più tempo.
import time
start_time = time.time()
# Qui va il tuo codice per eseguire azioni con Selenium
end_time = time.time()
print(f"Tempo di esecuzione: {end_time - start_time} secondi")
Questo piccolo frammento di codice ti aiuterà a determinare quanto tempo impiega una parte del codice. Usando questi "timer", puoi localizzare i "colli di bottiglia".
Identificazione dei punti deboli e loro ottimizzazione
Una volta trovato il pezzo di codice che "mangia" tempo, puoi agire. Forse accedi agli elementi dinamici più spesso del necessario oppure il tuo codice è diventato simile a degli "spaghetti". Il primo passo è l'identificazione, il secondo è l'azione.
Riduzione del numero di richieste: Controlla se non stai facendo troppi passaggi inutili tra pagine o aggiornamenti del DOM. Ad esempio, l'uso del metodo WebDriverWait
aiuta a eseguire lo script solo dopo il caricamento completo degli elementi desiderati.
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'))
)
Caching dei dati: Se lavori spesso con gli stessi dati, pensa al caching. Conserva i dati nelle variabili o in una cache per ridurre al minimo le operazioni costose in termini di risorse.
2. Migliorare la struttura dello script
Se il tuo codice è leggibile come una mappa della metropolitana senza indicazioni e nomi delle stazioni, è il momento di migliorarlo. Una struttura ottimale del codice è la chiave per una facile comprensione e, quindi, per una maggior resistenza agli errori.
Uso di pipeline di dati e soluzioni algoritmiche ottimali
Pensa a organizzare il tuo codice come una pipeline, dove ogni funzione o modulo si occupa di una parte specifica della logica. Dividere il codice in blocchi logici non solo migliora la leggibilità, ma facilita anche il debug.
def load_page(url):
driver.get(url)
def extract_data():
# Codice per estrarre dati
pass
def save_data():
# Codice per salvare dati
pass
load_page("http://example.com")
extract_data()
save_data()
Miglioramento della leggibilità e testabilità del codice
Segui il principio "una funzione — un compito". Questo semplifica il testing e il refactoring. Usa costanti nominate invece di numeri o stringhe "magiche" per una maggiore chiarezza.
MAX_RETRIES = 5
def fetch_data_with_retry():
for attempt in range(MAX_RETRIES):
try:
# Tentativo di richiesta dati
pass
except Exception as e:
print(f"Tentativo {attempt+1} fallito: {e}")
3. Se il codice può essere migliorato, deve esserlo
Usa attese esplicite invece di implicite
Le attese esplicite consentono di controllare esattamente quando Selenium esegue un'azione, attendendo la disponibilità degli elementi necessari. Invece di fare affidamento su attese implicite (ad esempio, implicitly_wait
), usa la libreria WebDriverWait
, che ti permette di impostare attese per elementi specifici in base a determinate condizioni (ad esempio, l'elemento è visibile, cliccabile, ecc.).
Esempio di utilizzo di attese esplicite
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"))
)
Assicurati che la pagina sia pronta
Dopo il caricamento della pagina, gli elementi potrebbero non essere immediatamente disponibili, soprattutto se il sito utilizza metodi di caricamento asincrono (AJAX). Usa document.readyState
per verificare che il documento sia completamente caricato prima di iniziare l'interazione.
Esempio di verifica del caricamento completo della pagina
def wait_for_page_load(driver):
WebDriverWait(driver, 10).until(
lambda d: d.execute_script("return document.readyState") == "complete"
)
Minimizza l'uso di time.sleep
Il metodo time.sleep()
costringe lo script ad aspettare un tempo fisso e rallenta il suo funzionamento, specialmente con lunghe attese. Usa invece WebDriverWait
, che è più flessibile e termina l'attesa non appena la condizione desiderata è soddisfatta.
Usa percorsi stabili per gli elementi
I locator fragili, come i percorsi XPath che dipendono da specifiche strutture HTML, potrebbero non funzionare più se la struttura del sito cambia. Per evitarlo, prova a usare locator più stabili, come gli attributi id
, name
, class
e data-*
, che sono più affidabili.
Esempio di utilizzo affidabile degli attributi
# Usa id per cercare, se disponibile
element = driver.find_element(By.ID, "submit_button")
# Se non c'è id, puoi usare l'attributo data-* o classi uniche
element = driver.find_element(By.CSS_SELECTOR, "[data-role='main-button']")
Chiudi popup e banner
Alcuni siti contengono popup che interferiscono con l'esecuzione dello script. Gestire questi elementi ti permette di evitare blocchi delle azioni principali.
Esempio di chiusura di un popup
from selenium.common.exceptions import ElementClickInterceptedException
try:
close_popup = driver.find_element(By.CLASS_NAME, "popup-close-button")
close_popup.click()
except (NoSuchElementException, ElementClickInterceptedException):
pass # Ignora se l'elemento non è trovato o impossibile chiudere
Configura la gestione del logging
Il logging aiuta a tracciare le azioni dello script e a identificare errori nel funzionamento. Usa il modulo integrato logging
per registrare ogni passaggio importante dello script, il che facilita il debug e l'analisi.
Esempio di configurazione del logging
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logging.info("Lo script è stato avviato")
logging.warning("Elemento non trovato, procedo con l'esecuzione")
logging.error("Si è verificato un errore")
Controlla la visibilità degli elementi prima dell'interazione
A volte gli elementi vengono caricati nella pagina, ma sono invisibili o non sono disponibili per l'interazione. Usa WebDriverWait
con la condizione element_to_be_clickable
per assicurarti che l'elemento sia disponibile prima di cliccarci sopra o inserire dati.
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "button_id"))
)
element.click()
Gestisci errori di connessione e timeout
Durante lo scraping dei siti web, possono verificarsi errori di connessione o timeout quando il server non risponde. Configura la gestione di questi errori per consentire allo script di saltare o ripetere le azioni in caso di inattività temporanea del sito.
Esempio di gestione degli errori di connessione
from selenium.common.exceptions import TimeoutException
try:
driver.get("https://example.com")
except TimeoutException:
logging.error("Impossibile connettersi alla pagina. Passo al prossimo compito.")
Chiudi il browser
Per evitare accumuli di risorse e chiudere il browser in caso di errori, utilizza sempre try-finally
o strutture simili per terminare correttamente l'esecuzione.
try:
# Azioni con Selenium
pass
finally:
driver.quit() # Chiusura del browser
4. Errori comuni dei principianti
Non dimenticare di aggiornare i web driver e le librerie. Questo ti aiuta a evitare incompatibilità e errori legati agli aggiornamenti del browser e ai cambiamenti nelle API di Selenium.
Infine, se il tuo script spesso "crasha" senza motivo apparente, potrebbe essere che il tuo server di test stia bloccando troppe richieste frequenti. Controlla se stai violando le regole di accesso e considera l'uso di proxy server o l'aggiustamento della frequenza delle richieste.
L'ottimizzazione degli script non è solo una questione tecnica, è un'arte che si acquisisce con l'esperienza. Spero che i consigli di oggi ti aiutino a creare script affidabili e stabili, pronti a gestire qualsiasi carico.
GO TO FULL VERSION