Ștergerea paginilor web în Python cu supă frumoasă Căutarea și modificarea DOM

În ultimul tutorial, ați învățat elementele de bază ale bibliotecii frumoase de supă. Pe lângă navigarea arborelui DOM, puteți căuta și elemente cu un anumit clasă sau id. De asemenea, puteți modifica copacul DOM utilizând această bibliotecă. 

În acest tutorial, veți afla despre diferite metode care vă vor ajuta în căutarea și modificările. Vom scoate aceeași pagină Wikipedia despre Python din ultimul nostru tutorial.

Filtre pentru căutarea arborelui

Supa frumoasă are o mulțime de metode pentru căutarea arborelui DOM. Aceste metode sunt foarte asemănătoare și iau aceleași tipuri de filtre ca și argumentele. Prin urmare, este logic să înțelegeți corect diferitele filtre înainte de a citi despre metodele respective. Voi folosi același lucru Găsiți toate() pentru a explica diferența dintre diferitele filtre.

Cel mai simplu filtru pe care îl puteți trece la orice metodă de căutare este un șir. Suprafața superbă va căuta apoi prin document pentru a găsi o etichetă care se potrivește exact cu șirul.

pentru titlu în soup.find_all ('h2'): print (heading.text) # Cuprins # Istorie [editați] # Caracteristici și filozofie [editați] # Sintaxă și semantică [modifică] # Biblioteci [ #… si asa mai departe.

De asemenea, puteți trece un obiect de expresie obișnuită la Găsiți toate() metodă. De data aceasta, Supa Superioară va filtra arborele prin potrivirea tuturor etichetelor împotriva unei expresii regulate date.

importul pentru titlu în soup.find_all (re.compile ("^ h [1-6]")): print (titlu.name + "+ head.text.strip ()) # h1 Python Cuprins # h2 Istorie [edit] # h2 Caracteristici și filozofie [edit] # h2 Sintaxă și semantică [edit] # h3 Indentare [editați] # h3 Declarații și flux de control [edit].

Codul va căuta toate etichetele care încep cu "h" și vor fi urmate de o cifră de la 1 la 6. Cu alte cuvinte, acesta va căuta toate etichetele de titlu din document.

În loc să utilizați regex, ați putea obține același rezultat trecând o listă cu toate etichetele pe care doriți să o potriviți frumos cu supa.

pentru titlu în soup.find_all (["h1", "h2", "h3", "h4", "h5", "h6"]): print (titlu.name +

Puteți trece, de asemenea Adevărat ca parametru pentru Găsiți toate() metodă. Codul va returna apoi toate etichetele din document. Rezultatul de mai jos înseamnă că în prezent există 4339 de etichete pe pagina Wikipedia pe care o analizăm.

len (soup.find_all (adevărat)) # 4339

Dacă încă nu reușiți să găsiți ceea ce căutați cu oricare dintre filtrele de mai sus, puteți defini funcția proprie, care ia un element ca singurul său argument. De asemenea, funcția trebuie să revină Adevărat dacă există un meci și Fals in caz contrar. În funcție de ceea ce aveți nevoie, puteți face ca funcția să fie atât de complicată încât trebuie să fie pentru a face treaba. Iată un exemplu foarte simplu:

def big_lists (tag): return len (tag.contents)> 20 și tag.name == 'ul' len (soup.find_all (big_lists)) # 13

Funcția de mai sus trece prin aceeași pagină Wikipedia Python și caută liste neordonate care au mai mult de 20 de copii.

Căutarea arborelui DOM utilizând funcțiile încorporate

Una dintre metodele cele mai populare pentru căutarea prin DOM este Găsiți toate(). Acesta va trece prin toți descendenții etichetei și va returna o listă a tuturor descendenților care corespund criteriilor dvs. de căutare. Această metodă are următoarea semnătură:

find_all (nume, attrs, recursiv, șir, limită, ** kwargs)

Nume Argumentul este numele etichetei pe care doriți ca această funcție să o caute în timp ce trece prin arbore. Sunteți liber să furnizați un șir, o listă, o expresie regulată, o funcție sau o valoare Adevărat ca nume.

De asemenea, puteți filtra elementele din arborele DOM, pe baza unor atribute diferite, cum ar fi id, href, etc Puteți obține, de asemenea, toate elementele cu un atribut specific, indiferent de valoarea sa folosind atribut = True. Căutarea elementelor cu o anumită clasă este diferită de căutarea atributelor obișnuite. De cand clasă este un cuvânt cheie rezervat în Python, va trebui să utilizați clasă_ cuvinte cheie atunci când căutați elemente cu o anumită clasă.

importul re len (soup.find_all (id = adevărat)) # 425 len (soup.find_all (class_ = adevărat)) # 1734 len (soup.find_all (class _ = "mw-headline" (href = adevărat)) # 1410 len (soup.find_all (href = re.compile ("python"))) # 102

Puteți vedea că documentul are 1.734 etichete cu a clasă atribut și 425 de etichete cu un id atribut. Dacă aveți nevoie doar de primele câteva dintre aceste rezultate, puteți trece un număr al metodei ca valoare limită. Trecerea acestei valori va instrui Supa Superioară să nu mai caute mai multe elemente după ce a ajuns la un anumit număr. Iată un exemplu:

soup.find_all (clasa _ = "mw-titlu", limit = 4) # Istorie # Caracteristici și filozofie # Sintaxă și semantică # zimțuire

Când utilizați Găsiți toate() , spuneți sufletului frumos să treacă prin toți descendenții unei etichete date pentru a găsi ceea ce căutați. Uneori, doriți să căutați un element numai în copiii direct pe o etichetă. Acest lucru poate fi realizat prin trecere recursiv = False la Găsiți toate() metodă.

len (soup.head.find_all ("meta", recursive = False)) # 6 len (soup.html.find_all ("meta" ) # 6

Dacă sunteți interesat să găsiți un singur rezultat pentru o anumită interogare de căutare, puteți utiliza găsi() metodă de ao găsi în loc să treacă Limita = 1 la Găsiți toate(). Singura diferență dintre rezultatele returnate de aceste două metode este aceea Găsiți toate() returnează o listă cu un singur element și găsi() returnează rezultatul.

soup.find_all ("h2", limita = 1) # [

Cuprins

] soup.find ("h2") #

Cuprins

găsi() și Găsiți toate() metode de căutare prin toți descendenții unei etichete date pentru a căuta un element. Există zece alte metode foarte asemănătoare pe care le puteți utiliza pentru a itera prin arborele DOM în direcții diferite.

(numele, atribuirea, șirul, limita, ** kwargs) find_next_sibling (nume, atribut, șir, ** kwargs) find_parents (nume, (nume, atribuire, șir, limită, ** kwargs) find_next (nume, atribut, șir, kwargs) find_previous_siblings (nume, ** kwargs) find_all_previous (nume, atribuire, șir, limită, ** kwargs) find_previous (nume, atribuire, șir, ** kwargs)

find_parent () și find_parents () metode traversează copacul DOM pentru a găsi elementul dat. find_next_sibling () și find_next_siblings () metodele vor repeta peste toți frații din elementul care vin după cel curent. În mod similar, find_previous_sibling () și find_previous_siblings () metodele vor itera asupra tuturor fraților din elementul care vin înaintea celui actual.

 găsește următorul() și find_all_next () metodele vor itera peste toate etichetele și șirurile care vin după elementul curent. În mod similar, find_previous () și find_all_previous () metodele vor itera peste toate etichetele și șirurile care vin în fața elementului curent.

De asemenea, puteți căuta elemente utilizând selectori CSS cu ajutorul funcției Selectați() metodă. Iată câteva exemple:

("h2: nth-of-type (1)") # [#]

Cuprins

] len (soup.select ("p> a: nth-of-type (2)")) # ("[class = = secțiune]")) # 80 len (sup.select ("[class $ = section]

Modificarea arborelui

Puteți căuta nu numai prin arborele DOM pentru a găsi un element, ci și să îl modificați. Este foarte ușor să redenumiți o etichetă și să modificați atributele acesteia.

head_tag ​​= sup.select ("h2: nth-of-type (2)") [0] heading_tag.name = "h3" 

Feat ... head_tag ​​['class'] = 'TitluChanged' print (title_tag) #

Continuând din ultimul exemplu, puteți înlocui conținutul unei etichete cu un șir dat folosind .şir atribut. Dacă nu doriți să înlocuiți conținutul, ci să adăugați ceva suplimentar la sfârșitul etichetei, puteți utiliza funcția adăuga() metodă. 

În mod similar, dacă doriți să inserați ceva în interiorul unei etichete într-o anumită locație, puteți utiliza funcția introduce() metodă. Primul parametru pentru această metodă este poziția sau indexul la care doriți să inserați conținutul, iar al doilea parametru este conținutul în sine. Puteți să eliminați tot conținutul din interiorul unei etichete folosind clar() metodă. Acest lucru vă va lăsa doar cu eticheta în sine și cu atributele acesteia.

title_tag.string = "Caracteristici și filosofie" print (title_tag) # 

Caracteristici și filozofie

head_tag.append ("[Anexă această parte]") print (heading_tag) #

Caracteristici și filozofie [anexat la această parte].

print (title_tag.contents) # ['Caracteristici și filozofie', '[anexat la această parte].'] heading_tag.insert (1, 'Inserted this part'

Caracteristici și filozofie A introdus această parte [Anexă la această parte].

head_tag.clear () print (heading_tag) #

La începutul acestei secțiuni, ați selectat un titlu de nivel 2 din document și l-ați modificat la un titlu de nivel trei. Folosind din nou același selector, vă vom arăta acum următoarea poziție de nivel două care a venit după original. Acest lucru are sens, deoarece titlul original nu mai este un titlu de nivel doi. 

Poziția inițială poate fi acum selectată utilizând h3: nth-de tip (2). Dacă doriți complet să eliminați un element sau o etichetă și tot conținutul din interiorul acestuia din arbore, puteți utiliza descompune() metodă.

supp.select ("h3: n-a-tip (2)") [0] #  supp.select ("h3: nth-of-type (3)") [0] # 

zimțuire... sup.select ("h3: nth-of-type (2)") [0] .decompose () sup.select ("

zimțuire...

După ce ați descompus sau ați desființat poziția originală, locul în locul al treilea își înlocuiește poziția.

Dacă doriți să eliminați o etichetă și conținutul acesteia din arbore, dar nu doriți să distrugeți complet eticheta, puteți folosi extrage() metodă. Această metodă va returna eticheta pe care a extras-o. Veți avea acum doi copaci diferiți pe care îi puteți analiza. Rădăcina copacului nou va fi eticheta pe care tocmai ați extras-o.

head_tree = soup.select ("h3: nth-of-type (2)") [0] .extract () len (head_tree.contents) # 2

Puteți, de asemenea, să înlocuiți o etichetă în interiorul arborelui cu altceva de la alegerea dvs. utilizând înlocui cu() metodă. Această metodă va returna eticheta sau șirul pe care le-a înlocuit. Poate fi util dacă doriți să plasați conținutul înlocuit în altă parte în document.

soup.h1 # 

Python (limba de programare)

bold_tag ​​= soup.new_tag ("b") bold_tag.string = "Python" soup.h1.replace_with (bold_tag) imprimare (soup.h1) # Nici un print (soup.b) # Piton

În codul de mai sus, titlul principal al documentului a fost înlocuit cu a b etichetă. Documentul nu mai are un document h1 tag-ul, și de aceea Print (soup.h1) acum se imprimă Nici unul.

Gândurile finale

După ce ați citit cele două tutoriale din această serie, acum ar trebui să puteți analiza diferite pagini web și să extrageți date importante din document. De asemenea, ar trebui să puteți prelua pagina web originală, să o modificați pentru a se potrivi nevoilor dvs. și să salvați versiunea modificată local.

Dacă aveți întrebări cu privire la acest tutorial, vă rugăm să ne anunțați în comentarii.

Cod