1. Nozioni di base sul lavoro con strutture HTML complesse
Prima di iniziare ad analizzare i markup HTML complessi, è importante capire perché l’HTML può essere così confuso. Gli sviluppatori web spesso usano elementi annidati complessi per organizzare il contenuto, il che può trasformarsi in un vero incubo per chi cerca di estrarre dati da queste pagine. Ma non preoccuparti: con un buon piano e gli strumenti giusti, te la caverai senza problemi!
Analisi dell’albero HTML
Immagina un documento HTML come un albero: ogni elemento è
un nodo che può contenere testo o altri nodi. In cima a questo albero c’è html
, seguito da
head
e body
, e dopo troviamo
vari elementi figli. Gli elementi annidati si trovano
più in profondità in questo albero.
Esempio di una semplice struttura HTML:
<html>
<head>
<title>Esempio</title>
</head>
<body>
<div class="content">
<h1>Titolo</h1>
<p>Paragrafo 1</p>
<p>Paragrafo 2</p>
<div class="nested">
<ul>
<li>Elemento 1</li>
<li>Elemento 2</li>
<li><span>Elemento 3</span></li>
</ul>
</div>
</div>
</body>
</html>
Come vedi, abbiamo un div
con la classe
nested
, che contiene un ul
, che
a sua volta è pieno di li
. Questo è un esempio
di come gli elementi possono essere annidati.
2. BeautifulSoup
per l’estrazione dei dati
Estrazione dei dati dagli elementi annidati
Ripassiamo come funziona BeautifulSoup. Usiamo
BeautifulSoup per estrarre il testo dalla lista
li
. È ora di diventare veri detective e raccogliere
dati dalle nostre strutture annidate.
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
nested_items = soup.select('.nested ul li')
for item in nested_items:
print(item.get_text())
Risultato:
Elemento 1
Elemento 2
Elemento 3
Come puoi vedere, abbiamo utilizzato il metodo select
con
un selettore CSS per trovare tutti i li
all’interno
dell’elemento con classe nested
. Il metodo
get_text()
permette di estrarre testo
direttamente dagli elementi trovati.
3. Lavorare con elementi multilivello
A volte i dati non si trovano solo in profondità nella struttura, ma sono distribuiti su diversi livelli, rendendo il compito di estrarli più complesso. Vediamo come estrarre dati da un albero HTML più complesso.
Esempio di una struttura complessa:
<html>
<body>
<div class="wrapper">
<div class="header">
<h1>Questo è un titolo</h1>
</div>
<div class="content">
<div class="article">
<h2>Articolo 1</h2>
<p>Contenuto articolo 1</p>
</div>
<div class="article">
<h2>Articolo 2</h2>
<p>Contenuto articolo 2</p>
</div>
</div>
<div class="footer">
<p>Informazioni di contatto</p>
</div>
</div>
</body>
</html>
Estrazione dei dati dai livelli
Proviamo ora a estrarre i titoli di tutti gli articoli e i loro contenuti.
articles = soup.select('.content .article')
for article in articles:
title = article.find('h2').get_text()
content = article.find('p').get_text()
print(f'Titolo: {title}')
print(f'Contenuto: {content}\n')
Output atteso:
Titolo: Articolo 1
Contenuto: Contenuto articolo 1
Titolo: Articolo 2
Contenuto: Contenuto articolo 2
Utilizziamo una combinazione di metodi select
e
find
per raggiungere i nostri obiettivi.
select
aiuta a trovare l’elemento genitore, mentre
find
estrae le informazioni dai figli.
4. Caratteristiche del lavoro con elementi annidati
Analizzando le pagine web, potresti imbatterti in problemi come la presenza di più elementi annidati con le stesse classi o tag. In questi casi, l’uso della ricerca contestuale e l’identificazione chiara degli elementi necessari aiutano a evitare errori.
Esempio di nidificazione complessa:
<html>
<body>
<div class="container">
<div class="item">
<h2>Numero 1</h2>
<div class="details">Dettagli 1</div>
</div>
<div class="item">
<h2>Numero 2</h2>
<div class="details">Dettagli 2</div>
<div class="additional">
<div class="info">Info aggiuntive</div>
</div>
</div>
</div>
</body>
</html>
Estrazione dati con attenzione alla nidificazione
Per evitare confusione, dovresti individuare elementi più specifici:
items = soup.select('.container .item')
for item in items:
number = item.find('h2').get_text()
details = item.select_one('.details').get_text()
additional_info = item.select_one('.additional .info')
print(f'Numero: {number}')
print(f'Dettagli: {details}')
if additional_info:
print(f'Informazioni aggiuntive: {additional_info.get_text()}')
print()
Qui utilizziamo il metodo select_one
, che
restituisce solo il primo elemento trovato, per evitare
duplicazioni dai blocchi aggiuntivi.
5. Aspetti pratici ed errori comuni
Lavorando con strutture HTML complesse è facile perdersi o
incontrare errori. Uno degli errori comuni è
cercare di accedere a un elemento inesistente, causando un
AttributeError
. Per evitarlo, controlla sempre
l’esistenza dell’elemento prima di lavorarci sopra.
Un’altra cosa importante è che non sempre bisogna estrarre i dati subito "di fretta". A volte è utile fare un’analisi preliminare della struttura, usare stampe di debug e verificare i risultati intermedi.
Nei progetti reali, le competenze per lavorare con strutture HTML annidate possono essere fondamentali. Questo si applica non solo al web scraping, ma anche al testing delle interfacce web, automazione dei test e persino all’analisi dei dati da API complesse, dove le risposte possono avere un formato strutturato e annidato.
GO TO FULL VERSION