beautifulsoup
Elementi di localizzazione
Ricerca…
Trova un testo dopo un elemento in BeautifulSoup
Immagina di avere il seguente codice HTML:
<div>
<label>Name:</label>
John Smith
</div>
E devi localizzare il testo "John Smith" dopo l'elemento label
.
In questo caso, è possibile individuare l'elemento label
base al testo e quindi utilizzare la proprietà .next_sibling
:
from bs4 import BeautifulSoup
data = """
<div>
<label>Name:</label>
John Smith
</div>
"""
soup = BeautifulSoup(data, "html.parser")
label = soup.find("label", text="Name:")
print(label.next_sibling.strip())
Stampa John Smith
.
Utilizzare i selettori CSS per individuare gli elementi in BeautifulSoup
BeautifulSoup ha un supporto limitato per i selettori CSS , ma copre quelli più comunemente usati. Usa il metodo select()
per trovare più elementi e select_one()
per trovare un singolo elemento.
Esempio di base:
from bs4 import BeautifulSoup
data = """
<ul>
<li class="item">item1</li>
<li class="item">item2</li>
<li class="item">item3</li>
</ul>
"""
soup = BeautifulSoup(data, "html.parser")
for item in soup.select("li.item"):
print(item.get_text())
stampe:
item1
item2
item3
Individuazione dei commenti
Per individuare i commenti in BeautifulSoup
, utilizzare l'argomento text
(o string
nelle versioni recenti) verificando il tipo da Comment
:
from bs4 import BeautifulSoup
from bs4 import Comment
data = """
<html>
<body>
<div>
<!-- desired text -->
</div>
</body>
</html>
"""
soup = BeautifulSoup(data, "html.parser")
comment = soup.find(text=lambda text: isinstance(text, Comment))
print(comment)
Stampa il desired text
.
Funzioni filtro
BeautifulSoup consente di filtrare i risultati fornendo una funzione per find_all
e funzioni simili. Questo può essere utile per i filtri complessi e uno strumento per il riutilizzo del codice.
Utilizzo di base
Definisci una funzione che accetta un elemento come unico argomento. La funzione dovrebbe restituire True
se l'argomento corrisponde.
def has_href(tag):
'''Returns True for tags with a href attribute'''
return bool(tag.get("href"))
soup.find_all(has_href) #find all elements with a href attribute
#equivilent using lambda:
soup.find_all(lambda tag: bool(tag.get("href")))
Un altro esempio che trova tag con un valore href
che non iniziano con
Fornire ulteriori argomenti per filtrare le funzioni
Poiché la funzione passata a find_all
può prendere solo un argomento, a volte è utile creare "fabbriche di funzioni" che producano funzioni utilizzabili in find_all
. Questo è utile per rendere le tue funzioni di ricerca dei tag più flessibili.
def present_in_href(check_string):
return lambda tag: tag.get("href") and check_string in tag.get("href")
soup.find_all(present_in_href("/partial/path"))
Accesso ai tag interni e ai loro attributi del tag inizialmente selezionato
Supponiamo che tu abbia un html
dopo aver selezionato con soup.find('div', class_='base class')
:
from bs4 import BeautifulSoup
soup = BeautifulSoup(SomePage, 'lxml')
html = soup.find('div', class_='base class')
print(html)
<div class="base class">
<div>Sample text 1</div>
<div>Sample text 2</div>
<div>
<a class="ordinary link" href="https://example.com">URL text</a>
</div>
</div>
<div class="Confusing class"></div>
'''
E se vuoi accedere a <a>
tag href
, puoi farlo in questo modo:
a_tag = html.a
link = a_tag['href']
print(link)
https://example.com
Ciò è utile quando non puoi selezionare direttamente il tag <a>
perché gli attrs
non ti danno un'identificazione univoca, ci sono altri tag <a>
"gemelli" nella pagina analizzata. Ma puoi selezionare in modo univoco un tag principale che contiene <a>
necessari.
Raccolta di elementi opzionali e / o dei loro attributi da serie di pagine
Consideriamo la situazione quando analizzi il numero di pagine e desideri raccogliere il valore dall'elemento facoltativo (che può essere presentato in una pagina e può essere assente in un'altra) per una pagina paticolare.
Inoltre, l'elemento stesso, ad esempio, è l' elemento più comune della pagina, in altre parole nessun attributo specifico può individuarlo in modo univoco. Ma vedi che puoi selezionare correttamente il suo elemento genitore e conosci il numero dell'ordine dell'elemento desiderato nel rispettivo livello di nidificazione.
from bs4 import BeautifulSoup
soup = BeautifulSoup(SomePage, 'lxml')
html = soup.find('div', class_='base class') # Below it refers to html_1 and html_2
L'elemento ricercato è facoltativo, quindi potrebbero esserci 2 situazioni per l' html
:
html_1 = '''
<div class="base class"> # №0
<div>Sample text 1</div> # №1
<div>Sample text 2</div> # №2
<div>!Needed text!</div> # №3
</div>
<div>Confusing div text</div> # №4
'''
html_2 = '''
<div class="base class"> # №0
<div>Sample text 1</div> # №1
<div>Sample text 2</div> # №2
</div>
<div>Confusing div text</div> # №4
'''
Se hai html_1
puoi raccogliere !Needed text!
dal tag №3 in questo modo:
wanted tag = html_1.div.find_next_sibling().find_next_sibling() # this gives you whole tag №3
Inizialmente ottiene №1 div
, quindi 2 volte passa al div
successivo allo stesso livello di nidificazione per arrivare a №3.
wanted_text = wanted_tag.text # extracting !Needed text!
L'utilità di questo approccio arriva quando ottieni html_2
- l'approccio non ti darà errore, darà None
:
print(html_2.div.find_next_sibling().find_next_sibling())
None
L'uso di find_next_sibling()
qui è cruciale perché limita la ricerca degli elementi in base al rispettivo livello di nidificazione. Se utilizzi find_next()
tag №4 verrà raccolto e non lo vuoi:
print(html_2.div.find_next().find_next())
<div>Confusing div text</div>
Puoi anche esplorare find_previous_sibling()
e find_previous()
che funzionano in modo opposto.
Tutte le funzioni descritte hanno le loro diverse varianti per catturare tutti i tag, non solo il primo:
find_next_siblings()
find_previous_siblings()
find_all_next()
find_all_previous()