Schöne Suppe - Navigieren nach Tags

In diesem Kapitel werden wir uns mit dem Navigieren nach Tags befassen.

Unten ist unser HTML-Dokument -

>>> html_doc = """
<html><head><title>Tutorials Point</title></head>
<body>
<p class="title"><b>The Biggest Online Tutorials Library, It's all Free</b></p>
<p class="prog">Top 5 most used Programming Languages are:
<a href="https://www.tutorialspoint.com/java/java_overview.htm" class="prog" id="link1">Java</a>,
<a href="https://www.tutorialspoint.com/cprogramming/index.htm" class="prog" id="link2">C</a>,
<a href="https://www.tutorialspoint.com/python/index.htm" class="prog" id="link3">Python</a>,
<a href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" class="prog" id="link4">JavaScript</a> and
<a href="https://www.tutorialspoint.com/ruby/index.htm" class="prog" id="link5">C</a>;
as per online survey.</p>
<p class="prog">Programming Languages</p>
"""
>>>
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html_doc, 'html.parser')
>>>

Basierend auf dem obigen Dokument werden wir versuchen, von einem Teil des Dokuments zu einem anderen zu wechseln.

Untergehen

Eines der wichtigsten Elemente in jedem HTML-Dokument sind Tags, die andere Tags / Zeichenfolgen (untergeordnete Elemente des Tags) enthalten können. Beautiful Soup bietet verschiedene Möglichkeiten zum Navigieren und Durchlaufen der Kinder des Tags.

Navigieren mit Tag-Namen

Die einfachste Möglichkeit, einen Analysebaum zu durchsuchen, besteht darin, das Tag anhand seines Namens zu durchsuchen. Wenn Sie das <head> -Tag möchten, verwenden Sieoup.head -

>>> soup.head
<head>&t;title>Tutorials Point</title></head>
>>> soup.title
<title>Tutorials Point</title>

So erhalten Sie ein bestimmtes Tag (wie das erste <b> -Tag) im <body> -Tag.

>>> soup.body.b
<b>The Biggest Online Tutorials Library, It's all Free</b>

Wenn Sie einen Tag-Namen als Attribut verwenden, erhalten Sie nur das erste Tag mit diesem Namen.

>>> soup.a
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>

Um alle Attribute des Tags abzurufen, können Sie die Methode find_all () verwenden.

>>> soup.find_all("a")
[<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>, <a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>, <a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>, <a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>, <a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>]>>> soup.find_all("a")
[<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>, <a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>, <a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>, <a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>, <a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>]

.inhalte und .kinder

Wir können die Kinder des Tags in einer Liste nach seinen .contents suchen -

>>> head_tag = soup.head
>>> head_tag
<head><title>Tutorials Point</title></head>
>>> Htag = soup.head
>>> Htag
<head><title>Tutorials Point</title></head>
>>>
>>> Htag.contents
[<title>Tutorials Point</title>
>>>
>>> Ttag = head_tag.contents[0]
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.contents
['Tutorials Point']

Das BeautifulSoup-Objekt selbst hat untergeordnete Elemente. In diesem Fall ist das <html> -Tag das untergeordnete Element des BeautifulSoup-Objekts.

>>> len(soup.contents)
2
>>> soup.contents[1].name
'html'

Ein String hat keine .contents, weil er nichts enthalten kann -

>>> text = Ttag.contents[0]
>>> text.contents
self.__class__.__name__, attr))
AttributeError: 'NavigableString' object has no attribute 'contents'

Verwenden Sie den Generator .children, um auf die untergeordneten Elemente des Tags zuzugreifen, anstatt sie als Liste abzurufen.

>>> for child in Ttag.children:
print(child)
Tutorials Point

.Nachkommenschaft

Mit dem Attribut .descendants können Sie alle untergeordneten Elemente eines Tags rekursiv durchlaufen.

seine direkten Kinder und die Kinder seiner direkten Kinder und so weiter -

>>> for child in Htag.descendants:
print(child)
<title>Tutorials Point</title>
Tutorials Point

Das <head> -Tag hat nur ein untergeordnetes Element, aber zwei Nachkommen: das <title> -Tag und das untergeordnete Element des <title> -Tags. Das Beautifulsoup-Objekt hat nur ein direktes untergeordnetes Element (das <html> -Tag), aber es hat eine ganze Reihe von Nachkommen -

>>> len(list(soup.children))
2
>>> len(list(soup.descendants))
33

.string

Wenn das Tag nur ein Kind hat und dieses Kind ein NavigableString ist, wird das Kind als .string - zur Verfügung gestellt.

>>> Ttag.string
'Tutorials Point'

Wenn das einzige untergeordnete Tag eines Tags ein anderes Tag ist und dieses Tag eine .string-Zeichenfolge hat, wird davon ausgegangen, dass das übergeordnete Tag dieselbe .string-Zeichenfolge wie sein untergeordnetes Tag hat.

>>> Htag.contents
[<title>Tutorials Point</title>]
>>>
>>> Htag.string
'Tutorials Point'

Wenn ein Tag jedoch mehr als eine Sache enthält, ist nicht klar, worauf sich .string beziehen soll. Daher ist .string als Keine definiert.

>>> print(soup.html.string)
None

.strings und stripped_strings

Wenn ein Tag mehr als eine Sache enthält, können Sie immer noch nur die Zeichenfolgen betrachten. Verwenden Sie den .strings-Generator -

>>> for string in soup.strings:
print(repr(string))
'\n'
'Tutorials Point'
'\n'
'\n'
"The Biggest Online Tutorials Library, It's all Free"
'\n'
'Top 5 most used Programming Languages are: \n'
'Java'
',\n'
'C'
',\n'
'Python'
',\n'
'JavaScript'
' and\n'
'C'
';\n \nas per online survey.'
'\n'
'Programming Languages'
'\n'

Verwenden Sie den Generator .stripped_strings, um zusätzliche Leerzeichen zu entfernen.

>>> for string in soup.stripped_strings:
print(repr(string))
'Tutorials Point'
"The Biggest Online Tutorials Library, It's all Free"
'Top 5 most used Programming Languages are:'
'Java'
','
'C'
','
'Python'
','
'JavaScript'
'and'
'C'
';\n \nas per online survey.'
'Programming Languages'

Aufsteigen

In einer "Stammbaum" -Analogie hat jedes Tag und jede Zeichenfolge ein übergeordnetes Element: das Tag, das es enthält:

.Elternteil

Verwenden Sie das Attribut .parent, um auf das übergeordnete Element des Elements zuzugreifen.

>>> Ttag = soup.title
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.parent
<head>title>Tutorials Point</title></head>

In unserem html_doc hat die Titelzeichenfolge selbst ein übergeordnetes Element: das <title> -Tag, das sie enthält

>>> Ttag.string.parent
<title>Tutorials Point</title>

Das übergeordnete Element eines Top-Level-Tags wie <html> ist das Beautifulsoup-Objekt selbst -

>>> htmltag = soup.html
>>> type(htmltag.parent)
<class 'bs4.BeautifulSoup'>

Die .parent eines Beautifulsoup-Objekts ist definiert als None -

>>> print(soup.parent)
None

.Eltern

Verwenden Sie das Attribut .parents, um alle übergeordneten Elemente zu durchlaufen.

>>> link = soup.a
>>> link
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
>>>
>>> for parent in link.parents:
if parent is None:
print(parent)
else:
print(parent.name)
p
body
html
[document]

Seitwärts gehen

Unten ist ein einfaches Dokument -

>>> sibling_soup = BeautifulSoup("<a><b>TutorialsPoint</b><c><strong>The Biggest Online Tutorials Library, It's all Free</strong></b></a>")
>>> print(sibling_soup.prettify())
<html>
<body>
   <a>
      <b>
         TutorialsPoint
      </b>
      <c>
         <strong>
            The Biggest Online Tutorials Library, It's all Free
         </strong>
      </c>
   </a>
</body>
</html>

Im obigen Dokument befinden sich die Tags <b> und <c> auf derselben Ebene und beide sind untergeordnete Elemente desselben Tags. Sowohl das <b> als auch das <c> -Tag sind Geschwister.

.next_sibling und .previous_sibling

Verwenden Sie .next_sibling und .previous_sibling, um zwischen Seitenelementen zu navigieren, die sich auf derselben Ebene des Analysebaums befinden:

>>> sibling_soup.b.next_sibling
<c><strong>The Biggest Online Tutorials Library, It's all Free</strong></c>
>>>
>>> sibling_soup.c.previous_sibling
<b>TutorialsPoint</b>

Das <b> -Tag hat ein .next_sibling, aber kein .previous_sibling, da sich vor dem <b> -Tag auf derselben Ebene des Baums nichts befindet. Der gleiche Fall gilt für das <c> -Tag.

>>> print(sibling_soup.b.previous_sibling)
None
>>> print(sibling_soup.c.next_sibling)
None

Die beiden Zeichenfolgen sind keine Geschwister, da sie nicht dasselbe Elternteil haben.

>>> sibling_soup.b.string
'TutorialsPoint'
>>>
>>> print(sibling_soup.b.string.next_sibling)
None

.next_scribers und .previous_s Geschwisters

Um die Geschwister eines Tags zu durchlaufen, verwenden Sie .next_s Geschwister und .previous_s Geschwister.

>>> for sibling in soup.a.next_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>
',\n'
>a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>
',\n'
<a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>
' and\n'
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm"
id="link5">C</a>
';\n \nas per online survey.'
>>> for sibling in soup.find(id="link3").previous_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>
',\n'
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
'Top 5 most used Programming Languages are: \n'

Vor und zurück gehen

Kommen wir nun zu den ersten beiden Zeilen in unserem vorherigen Beispiel "html_doc" zurück -

&t;html><head><title>Tutorials Point</title></head>
<body>
<h4 class="tagLine"><b>The Biggest Online Tutorials Library, It's all Free</b></h4>

Ein HTML-Parser nimmt die oben genannte Zeichenfolge auf und wandelt sie in eine Reihe von Ereignissen um, z. B. "Öffnen eines <html> -Tags", "Öffnen eines <head> -Tags", "Öffnen des <title> -Tags", "Hinzufügen einer Zeichenfolge". "Schließen Sie das </ title> -Tag", "Schließen Sie das </ head> -Tag", "Öffnen Sie ein <h4> -Tag" und so weiter. BeautifulSoup bietet verschiedene Methoden zur Rekonstruktion der anfänglichen Analyse des Dokuments.

.next_element und .previous_element

Das Attribut .next_element eines Tags oder einer Zeichenfolge zeigt auf das, was unmittelbar danach analysiert wurde. Manchmal sieht es ähnlich aus wie .next_sibling, aber es ist nicht ganz dasselbe. Unten finden Sie das letzte <a> -Tag in unserem Beispieldokument "html_doc".

>>> last_a_tag = soup.find("a", id="link5")
>>> last_a_tag
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>
>>> last_a_tag.next_sibling
';\n \nas per online survey.'

Das .next_element dieses <a> -Tags, das unmittelbar nach dem <a> -Tag analysiert wurde, ist jedoch nicht der Rest dieses Satzes: Es ist das Wort "C":

>>> last_a_tag.next_element
'C'

Das obige Verhalten ist darauf zurückzuführen, dass im ursprünglichen Markup der Buchstabe „C“ vor diesem Semikolon stand. Der Parser stieß auf ein <a> -Tag, dann auf den Buchstaben „C“, dann auf das schließende </a> Tag, dann auf das Semikolon und den Rest des Satzes. Das Semikolon befindet sich auf derselben Ebene wie das <a> -Tag, aber der Buchstabe „C“ wurde zuerst gefunden.

Das Attribut .previous_element ist das genaue Gegenteil von .next_element. Es zeigt auf das Element, das unmittelbar vor diesem Element analysiert wurde.

>>> last_a_tag.previous_element
' and\n'
>>>
>>> last_a_tag.previous_element.next_element
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>

.next_elements und .previous_elements

Wir verwenden diese Iteratoren, um vorwärts und rückwärts zu einem Element zu gelangen.

>>> for element in last_a_tag.next_e lements:
print(repr(element))
'C'
';\n \nas per online survey.'
'\n'
<p class="prog">Programming Languages</p>
'Programming Languages'
'\n'