Sök…


Leta reda på en text efter ett element i BeautifulSoup

Föreställ dig att du har följande HTML:

<div>
    <label>Name:</label>
    John Smith
</div>

Och du måste hitta texten "John Smith" efter label .

I det här fallet kan du hitta label efter text och sedan använda .next_sibling egenskapen :

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())

Skriver ut John Smith .

Använda CSS-väljare för att hitta element i BeautifulSoup

BeautifulSoup har ett begränsat stöd för CSS-väljare , men täcker de vanligaste. Använd metoden select() för att hitta flera element och select_one() att hitta ett enda element.

Grundläggande exempel:

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())

Grafik:

item1
item2
item3

Hitta kommentarer

För att hitta kommentarer i BeautifulSoup använder du text (eller string i de senaste versionerna) och kontrollerar typen som ska 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)

Skriver ut desired text .

Filterfunktioner

Med BeautifulSoup kan du filtrera resultat genom att tillhandahålla en funktion för att find_all och liknande funktioner. Detta kan vara användbart för komplexa filter samt ett verktyg för återanvändning av kod.

Grundläggande användning

Definiera en funktion som tar ett element som enda argument. Funktionen ska returnera True om argumentet matchar.

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")))

Ett annat exempel som hittar taggar med ett href värde som inte börjar med

Tillhandahålla ytterligare argument för att filtrera funktioner

Eftersom funktionen som skickas till find_all bara kan ta ett argument är det ibland användbart att göra 'funktionsfabriker' som producerar funktioner som är lämpliga för användning i find_all . Detta är användbart för att göra dina taggfunktioner mer flexibla.

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"))

Få åtkomst till interna taggar och deras attribut för den ursprungligen valda taggen

Låt oss anta att du fick en html efter att ha valt med 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>
'''

Och om du vill få tillgång till <a> taggens href kan du göra det på detta sätt:

a_tag = html.a
link = a_tag['href']
print(link)

https://example.com

Detta är användbart när du inte direkt kan välja <a> -tagg eftersom det är attrs inte ger dig unik identifikation, det finns andra "tvilling" <a> -taggar på den parsade sidan. Men du kan på ett unikt sätt välja en överordnad tagg som innehåller nödvändig <a> .

Samla valfria element och / eller deras attribut från serier

Låt oss överväga situationen när du analyserar antal sidor och du vill samla värde från ett element som är valfritt (kan presenteras på en sida och kan vara frånvarande på en annan) för en patikulär sida.

Dessutom är själva elementet till exempel det vanligaste elementet på sidan, med andra ord kan inga specifika attribut unikt hitta det. Men du ser att du kan välja det överordnade elementet ordentligt och du vet önskat elementets ordernummer i respektive häckningsnivå.

from bs4 import BeautifulSoup

soup = BeautifulSoup(SomePage, 'lxml')
html = soup.find('div', class_='base class') # Below it refers to html_1 and html_2

Det önskade elementet är valfritt, så det kan finnas två situationer för 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
'''

Om du har html_1 du samla in !Needed text! från tagg nummer 3 på detta sätt:

wanted tag = html_1.div.find_next_sibling().find_next_sibling() # this gives you whole tag №3

Den får initialt №1 div , sedan byter 2 gånger till nästa div på samma häckningsnivå för att komma till №3.

wanted_text = wanted_tag.text # extracting !Needed text!

Användbarheten av detta tillvägagångssätt kommer när du får html_2 - tillvägagångssättet kommer inte att ge dig fel, det kommer att ge None :

print(html_2.div.find_next_sibling().find_next_sibling())
None

Att använda find_next_sibling() här är avgörande eftersom det begränsar elementets sökning med respektive häckningsnivå. Om du skulle använda find_next() samlas tagg nr 4 och du vill inte ha det:

print(html_2.div.find_next().find_next())
<div>Confusing div text</div>

Du kan också utforska find_previous_sibling() och find_previous() som fungerar tvärtom.

Alla beskrivna funktioner har sina miltiple- varianter för att fånga alla taggar, inte bara den första:

find_next_siblings()
find_previous_siblings()
find_all_next()
find_all_previous()


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow