Zoeken…


Zoek een tekst achter een element in BeautifulSoup

Stel je voor dat je de volgende HTML hebt:

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

En u moet de tekst "John Smith" achter het label element zoeken.

In dat geval kunt u het vinden label element door tekst en gebruik vervolgens .next_sibling eigenschap :

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

Prints John Smith .

CSS-selectors gebruiken om elementen in BeautifulSoup te vinden

BeautifulSoup biedt beperkte ondersteuning voor CSS-selectors , maar dekt de meestgebruikte. Gebruik select() methode select() om meerdere elementen te vinden en select_one() om een enkel element te vinden.

Basis voorbeeld:

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

prints:

item1
item2
item3

Reacties zoeken

Om opmerkingen in BeautifulSoup te vinden, gebruikt u het argument text (of string in de recente versies) en vinkt u het type aan als 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)

Drukt desired text .

Filter functies

Met BeautifulSoup kunt u resultaten filteren door een functie te find_all voor alle find_all en soortgelijke functies. Dit kan handig zijn voor complexe filters, maar ook als hulpmiddel voor hergebruik van code.

Basis gebruik

Definieer een functie waarvoor een element het enige argument is. De functie moet True retourneren als het argument overeenkomt.

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

Een ander voorbeeld dat tags vindt met een href waarde die niet beginnen

Aanvullende argumenten verstrekken voor filterfuncties

Omdat de functie die wordt doorgegeven aan find_all maar één argument kan bevatten, is het soms handig om 'functiefabrieken' te maken die functies geschikt maken voor gebruik in find_all . Dit is handig om uw tag-zoekfuncties flexibeler te maken.

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

Toegang tot interne tags en hun attributen van aanvankelijk geselecteerde tag

Laten we aannemen dat u een html hebt gekregen na het selecteren met 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>
'''

En als u toegang wilt tot de href <a> tag, kunt u dit op deze manier doen:

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

https://example.com

Dit is handig wanneer u niet rechtstreeks <a> -tag kunt selecteren omdat de attrs u geen unieke identificatie geven, er zijn andere "dubbele" <a> -tags in geparseerde pagina. Maar u kunt op unieke wijze een bovenliggende tag selecteren die de benodigde <a> bevat.

Het verzamelen van optionele elementen en / of hun attributen uit een reeks pagina's

Laten we de situatie bekijken wanneer u het aantal pagina's parseert en u waarde wilt verzamelen van een element dat optioneel is (kan op de ene pagina worden weergegeven en op een andere pagina afwezig zijn) voor een bepaalde pagina.

Bovendien is het element zelf bijvoorbeeld het meest gewone element op pagina, met andere woorden, geen specifieke attributen kunnen het uniek lokaliseren. Maar u ziet dat u het bovenliggende element correct kunt selecteren en dat u het bestelnummer van het gewenste element kent in het respectieve nestniveau.

from bs4 import BeautifulSoup

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

Wanted-element is optioneel, dus er kunnen 2 situaties zijn voor 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
'''

Als je html_1 hebt, kun je deze verzamelen !Needed text! van tag №3 op deze manier:

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

Het krijgt in eerste instantie №1 div , dan schakelt 2 keer over naar de volgende div op hetzelfde nestniveau om №3 te krijgen.

wanted_text = wanted_tag.text # extracting !Needed text!

Het nut van deze aanpak komt wanneer u html_2 krijgt - de aanpak geeft geen fouten, maar geeft None :

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

Het gebruik van find_next_sibling() hier is van cruciaal belang omdat het zoeken van elementen per respectief find_next_sibling() wordt beperkt. Als u find_next() wordt tag find_next() verzameld en wilt u het niet:

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

Je kunt ook find_previous_sibling() en find_previous() verkennen die recht tegenovergesteld werken.

Alle beschreven functies hebben hun miltiple- varianten om alle tags te vangen, niet alleen de eerste:

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow