Nell'ultimo tutorial, hai imparato le basi della libreria Beautiful Soup. Oltre alla navigazione dell'albero DOM, puoi anche cercare elementi con un dato classe
o id
. È inoltre possibile modificare l'albero DOM utilizzando questa libreria.
In questo tutorial, imparerai i diversi metodi che ti aiuteranno nella ricerca e nelle modifiche. Scatteremo la stessa pagina di Wikipedia su Python dal nostro ultimo tutorial.
Beautiful Soup ha molti metodi per cercare l'albero DOM. Questi metodi sono molto simili e utilizzano gli stessi tipi di filtri degli argomenti. Pertanto, ha senso comprendere correttamente i diversi filtri prima di leggere i metodi. Userò lo stesso trova tutto()
metodo per spiegare la differenza tra diversi filtri.
Il filtro più semplice che puoi passare a qualsiasi metodo di ricerca è una stringa. Beautiful Soup cercherà quindi nel documento per trovare un tag che corrisponda esattamente alla stringa.
per voce in soup.find_all ('h2'): print (heading.text) # Contenuto # Cronologia [modifica] # Funzioni e filosofia [modifica] # Sintassi e semantica [modifica] # Librerie [modifica] # Ambienti di sviluppo [modifica] #… e così via.
È anche possibile passare un oggetto di espressione regolare al trova tutto()
metodo. Questa volta, Beautiful Soup filtrerà l'albero abbinando tutti i tag a una determinata espressione regolare.
import re per heading in soup.find_all (re.compile ("^ h [1-6]")): print (heading.name + "+ heading.text.strip ()) # h1 Python (linguaggio di programmazione) # h2 Contenuti # h2 Storia [modifica] # h2 Caratteristiche e filosofia [modifica] # h2 Sintassi e semantica [modifica] # h3 Indentazione [modifica] # h3 Istruzioni e controllo flusso [modifica] # ... un così via.
Il codice cercherà tutti i tag che iniziano con "h" e sono seguiti da una cifra da 1 a 6. In altre parole, cercherà tutti i tag di intestazione nel documento.
Invece di usare espressioni regolari, potresti ottenere lo stesso risultato passando un elenco di tutti i tag che vuoi che Beautiful Soup corrisponda al documento.
per la voce in soup.find_all (["h1", "h2", "h3", "h4", "h5", "h6"]): print (heading.name + "+ heading.text.strip ())
Puoi anche passare Vero
come parametro per il trova tutto()
metodo. Il codice restituirà quindi tutti i tag nel documento. L'output qui sotto indica che ci sono attualmente 4.339 tag nella pagina di Wikipedia che stiamo analizzando.
len (soup.find_all (True)) # 4339
Se non si è ancora in grado di trovare ciò che si sta cercando con uno dei filtri precedenti, è possibile definire la propria funzione che accetta un elemento come unico argomento. Anche la funzione deve tornare Vero
se c'è una partita e falso
altrimenti. A seconda di ciò che ti serve, puoi rendere la funzione tanto complicata quanto dover fare il lavoro. Ecco un esempio molto semplice:
def big_lists (tag): return len (tag.contents)> 20 e tag.name == 'ul' len (soup.find_all (liste_lande)) # 13
La funzione sopra riportata sta analizzando la stessa pagina Python di Wikipedia e sta cercando liste non ordinate con più di 20 bambini.
Uno dei metodi più popolari per la ricerca attraverso il DOM è trova tutto()
. Passerà attraverso tutti i discendenti del tag e restituirà un elenco di tutti i discendenti che corrispondono ai tuoi criteri di ricerca. Questo metodo ha la seguente firma:
find_all (nome, attrs, ricorsivo, stringa, limite, ** kwargs)
Il nome
argomento è il nome del tag che si desidera che questa funzione cerchi mentre si attraversa l'albero. Sei libero di fornire una stringa, un elenco, un'espressione regolare, una funzione o il valore Vero
come un nome.
Puoi anche filtrare gli elementi nell'albero DOM sulla base di diversi attributi come id
, href
, ecc. Puoi anche ottenere tutti gli elementi con un attributo specifico indipendentemente dal suo valore Attributo = True
. La ricerca di elementi con una classe specifica è diversa dalla ricerca di attributi regolari. Da classe
è una parola chiave riservata in Python, dovrai usare il classe_
argomento della parola chiave quando si cercano elementi con una classe specifica.
import re len (soup.find_all (id = True)) # 425 len (soup.find_all (class_ = True)) # 1734 len (soup.find_all (class _ = "mw-headline")) # 20 len (soup.find_all (href = True)) # 1410 len (soup.find_all (href = re.compile ("python"))) # 102
Puoi vedere che il documento ha 1.734 tag con a classe
attributo e 425 tag con un id
attributo. Se ti servono solo i primi di questi risultati, puoi passare un numero al metodo come valore di limite
. Passando questo valore istruirai la bella zuppa a smettere di cercare più elementi una volta raggiunto un certo numero. Ecco un esempio:
soup.find_all (class _ = "mw-headline", limite = 4) # Storia # Caratteristiche e filosofia # Sintassi e semantica # dentellatura
Quando usi il trova tutto()
metodo, stai dicendo a Beautiful Soup di esaminare tutti i discendenti di un determinato tag per trovare quello che stai cercando. A volte, vuoi cercare un elemento solo nei bambini diretti su un tag. Questo può essere ottenuto passando ricorsiva = False
al trova tutto()
metodo.
len (soup.html.find_all ("meta")) # 6 len (soup.html.find_all ("meta", recursive = False)) # 0 len (soup.head.find_all ("meta", recursive = False) ) # 6
Se sei interessato a trovare solo un risultato per una particolare query di ricerca, puoi utilizzare il comando trova()
metodo per trovarlo invece di passare Limite = 1
a trova tutto()
. L'unica differenza tra i risultati restituiti da questi due metodi è quella trova tutto()
restituisce una lista con un solo elemento e trova()
restituisce solo il risultato.
soup.find_all ("h2", limite = 1) # [Contenuto
] soup.find ("h2") #Contenuto
Il trova()
e trova tutto()
i metodi cercano tutti i discendenti di un determinato tag per cercare un elemento. Esistono altri dieci metodi molto simili che è possibile utilizzare per scorrere l'albero DOM in diverse direzioni.
find_parents (nome, attrs, stringa, limite, ** kwargs) find_parent (nome, attrs, stringa, ** kwargs) find_next_siblings (nome, attrs, stringa, limite, ** kwargs) find_next_sibling (nome, attrs, stringa, ** kwargs) find_previous_siblings (nome, attrs, stringa, limite, ** kwargs) find_previous_sibling (nome, attrs, stringa, ** kwargs) find_all_next (nome, attrs, stringa, limite, ** kwargs) find_next (nome, attrs, stringa, ** kwargs) find_all_previous (nome, attrs, stringa, limite, ** kwargs) find_previous (nome, attrs, stringa, ** kwargs)
Il find_parent ()
e find_parents ()
i metodi attraversano l'albero DOM per trovare l'elemento dato. Il find_next_sibling ()
e find_next_siblings ()
i metodi verranno iterati su tutti i fratelli dell'elemento che vengono dopo quello corrente. Allo stesso modo, il find_previous_sibling ()
e find_previous_siblings ()
i metodi verranno iterati su tutti i fratelli dell'elemento che precede quello corrente.
Il trova il prossimo()
e find_all_next ()
i metodi eseguiranno iterazioni su tutti i tag e le stringhe che seguono l'elemento corrente. Allo stesso modo, il find_previous ()
e find_all_previous ()
i metodi eseguiranno iterazioni su tutti i tag e le stringhe che precedono l'elemento corrente.
Puoi anche cercare elementi usando selettori CSS con l'aiuto di selezionare()
metodo. Ecco alcuni esempi:
len (soup.select ("p a")) # 411 len (soup.select ("p> a")) # 291 soup.select ("h2: nth-of-type (1)") # [Contenuto
] len (soup.select ("p> a: nth-of-type (2)")) # 46 len (soup.select ("p> a: nth-of-type (10)")) # 6 len (soup.select ("[class * = section]")) # 80 len (soup.select ("[class $ = section]")) # 20
Non puoi solo cercare attraverso l'albero DOM per trovare un elemento ma anche modificarlo. È molto facile rinominare un tag e modificarne gli attributi.
heading_tag = soup.select ("h2: nth-of-type (2)") [0] heading_tag.name = "h3" print (heading_tag) #Feat ... heading_tag ['class'] = 'headingChanged' print (heading_tag) #
Continuando dal nostro ultimo esempio, puoi sostituire il contenuto di un tag con una determinata stringa usando il
.stringa
attributo. Se non vuoi sostituire il contenuto ma aggiungi qualcosa in più alla fine del tag, puoi utilizzare il comandoaggiungere()
metodo.Allo stesso modo, se desideri inserire qualcosa all'interno di un tag in una posizione specifica, puoi utilizzare il comando
inserire()
metodo. Il primo parametro per questo metodo è la posizione o l'indice a cui si desidera inserire il contenuto e il secondo parametro è il contenuto stesso. Puoi rimuovere tutto il contenuto all'interno di un tag usando ilchiaro()
metodo. Questo ti lascerà solo il tag stesso e i suoi attributi.heading_tag.string = "Caratteristiche e filosofia" print (heading_tag) #Caratteristiche e filosofia
heading_tag.append ("[Aggiunta di questa parte].") print (heading_tag) #Caratteristiche e filosofia [Aggiunta di questa parte].
print (heading_tag.contents) # ['Features and Philosophy', '[Appended This Part].'] heading_tag.insert (1, 'Inserted this part') stampa (titolo_tag) #Caratteristiche e filosofia Inserita questa parte [Aggiunta di questa parte].
heading_tag.clear () print (heading_tag) #All'inizio di questa sezione, hai selezionato un'intestazione di livello due dal documento e l'hai modificata in un'intestazione di livello tre. Usando di nuovo lo stesso selettore ora mostrerai il prossimo livello di due titoli che è arrivato dopo l'originale. Questo ha senso perché l'intestazione originale non è più un'intestazione di livello due.
L'intestazione originale può ora essere selezionata usando
h3: nth-of-type (2)
. Se si desidera rimuovere completamente un elemento o un tag e tutto il contenuto al suo interno dall'albero, è possibile utilizzare il comandodecomporsi()
metodo.soup.select ("h3: nth-of-type (2)") [0] # soup.select ("h3: nth-of-type (3)") [0] #dentellatura... soup.select ("h3: nth-of-type (2)") [0] .decompose () soup.select ("h3: nth-of-type (2)") [0] #
dentellatura...
Una volta decomposto o rimosso l'intestazione originale, l'intestazione nel terzo punto prende il suo posto.
Se vuoi rimuovere un tag e il suo contenuto dall'albero ma non vuoi distruggere completamente il tag, puoi utilizzare il comando
estratto()
metodo. Questo metodo restituirà il tag che ha estratto. Ora avrai due alberi diversi che puoi analizzare. La radice del nuovo albero sarà il tag che hai appena estratto.heading_tree = soup.select ("h3: nth-of-type (2)") [0] .extract () len (heading_tree.contents) # 2Puoi anche sostituire un tag all'interno dell'albero con qualcos'altro di tua scelta usando il
sostituirlo con()
metodo. Questo metodo restituirà il tag o la stringa che ha sostituito. Può essere utile se vuoi inserire il contenuto sostituito da qualche altra parte nel documento.soup.h1 #Python (linguaggio di programmazione)
bold_tag = soup.new_tag ("b") bold_tag.string = "Python" soup.h1.replace_with (bold_tag) print (soup.h1) # None print (soup.b) # PitoneNel codice precedente, l'intestazione principale del documento è stata sostituita con un
B
etichetta. Il documento non ha più unh1
tag, ed è per questostampa (soup.h1)
ora stampaNessuna
.Pensieri finali
Dopo aver letto i due tutorial di questa serie, ora dovresti essere in grado di analizzare pagine Web diverse ed estrarre dati importanti dal documento. Dovresti anche essere in grado di recuperare la pagina web originale, modificarla in base alle tue esigenze e salvare la versione modificata a livello locale.
Se avete domande su questo tutorial, fatemelo sapere nei commenti.