Beautiful Soup - Menavigasi menurut Tag

Pada bab ini, kita akan membahas tentang Menavigasi dengan Tag.

Di bawah ini adalah dokumen html kami -

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

Berdasarkan dokumen di atas, kita akan mencoba berpindah dari satu bagian dokumen ke dokumen lainnya.

Turun

Salah satu bagian penting dari elemen dalam setiap bagian dokumen HTML adalah tag, yang mungkin berisi tag / string lain (turunan tag). Beautiful Soup menyediakan berbagai cara untuk menavigasi dan mengulang anak-anak tag.

Menavigasi menggunakan nama tag

Cara termudah untuk mencari pohon parse adalah dengan mencari tag berdasarkan namanya. Jika Anda menginginkan tag <head>, gunakan soup.head -

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

Untuk mendapatkan tag tertentu (seperti <b> tag pertama) di tag <body>.

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

Menggunakan nama tag sebagai atribut hanya akan memberi Anda tag pertama dengan nama itu -

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

Untuk mendapatkan semua atribut tag, Anda dapat menggunakan metode find_all () -

>>> 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>]

.contents dan .children

Kita dapat mencari anak-anak tag dalam daftar dengan. Kontennya -

>>> 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']

Objek BeautifulSoup itu sendiri memiliki anak. Dalam kasus ini, tag <html> adalah anak dari objek BeautifulSoup -

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

Sebuah string tidak memiliki .contents, karena tidak dapat berisi apa pun -

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

Alih-alih menjadikannya sebagai daftar, gunakan generator .children untuk mengakses turunan dari tag -

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

.descendants

Atribut .descendants memungkinkan Anda melakukan iterasi pada semua turunan tag, secara rekursif -

anak langsungnya dan anak dari anak langsungnya dan seterusnya -

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

Tag <head> hanya memiliki satu turunan, tetapi memiliki dua turunan: tag <title> dan turunan dari tag <title>. Objek beautifulsoup hanya memiliki satu anak langsung (tag <html>), tetapi memiliki banyak turunan -

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

.tali

Jika tag hanya memiliki satu turunan, dan turunan itu adalah NavigableString, turunan tersebut akan tersedia sebagai .string -

>>> Ttag.string
'Tutorials Point'

Jika satu-satunya anak tag adalah tag lain, dan tag tersebut memiliki .string, maka tag induk dianggap memiliki .string yang sama dengan anaknya -

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

Namun, jika sebuah tag berisi lebih dari satu hal, maka tidak jelas apa yang harus dirujuk .string, jadi .string didefinisikan ke Tidak Ada -

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

.strings dan stripped_strings

Jika ada lebih dari satu hal di dalam tag, Anda masih dapat melihat stringnya saja. Gunakan generator .strings -

>>> 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'

Untuk menghapus spasi ekstra, gunakan generator .stripped_strings -

>>> 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'

Naik ke atas

Dalam analogi "pohon keluarga", setiap tag dan setiap string memiliki induk: tag yang memuatnya:

.induk

Untuk mengakses elemen induk dari elemen tersebut, gunakan atribut .parent.

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

Dalam html_doc kami, string judul itu sendiri memiliki induk: tag <title> yang berisi it−

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

Induk dari tag level atas seperti <html> adalah objek Beautifulsoup itu sendiri -

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

.Parent dari objek Beautifulsoup didefinisikan sebagai None -

>>> print(soup.parent)
None

.orangtua

Untuk mengulangi semua elemen orang tua, gunakan atribut .parents.

>>> 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]

Pergi ke samping

Di bawah ini adalah satu dokumen sederhana -

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

Dalam dokumen di atas, tag <b> dan <c> berada pada level yang sama dan keduanya adalah turunan dari tag yang sama. Baik tag <b> dan <c> adalah saudara kandung.

.next_sibling dan .previous_sibling

Gunakan .next_sibling dan .previous_sibling untuk bernavigasi di antara elemen halaman yang berada pada level yang sama dari pohon parse:

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

Tag <b> memiliki .next_sibling tetapi tidak ada .previous_sibling, karena tidak ada apa pun sebelum tag <b> di tingkat pohon yang sama, kasus yang sama dengan tag <c>.

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

Kedua string tersebut bukanlah saudara kandung, karena tidak memiliki induk yang sama.

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

.next_siblings dan .previous_siblings

Untuk melakukan iterasi pada saudara tag, gunakan .next_siblings dan .previous_siblings.

>>> 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'

Bolak-balik

Sekarang mari kita kembali ke dua baris pertama pada contoh “html_doc” sebelumnya -

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

Pengurai HTML menggunakan string karakter di atas dan mengubahnya menjadi rangkaian peristiwa seperti "buka tag <html>", "buka tag <head>", "buka tag <title>", "tambahkan string", “Tutup tag </title>”, “tutup tag </head>”, “buka tag <h4>” dan seterusnya. BeautifulSoup menawarkan metode berbeda untuk merekonstruksi penguraian awal dokumen.

.next_element dan .previous_element

Atribut .next_element dari sebuah tag atau string menunjuk ke apa pun yang diurai segera setelahnya. Terkadang terlihat mirip dengan .next_sibling, namun tidak sepenuhnya sama. Di bawah ini adalah tag <a> terakhir dalam dokumen contoh "html_doc" kami.

>>> 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.'

Namun .next_element dari tag <a> itu, hal yang diurai segera setelah tag <a>, bukanlah sisa dari kalimat itu: itu adalah kata "C":

>>> last_a_tag.next_element
'C'

Perilaku di atas karena dalam markup asli, huruf "C" muncul sebelum titik koma. Pengurai menemukan tag <a>, lalu huruf “C”, lalu tag penutup </a>, lalu titik koma dan sisa kalimat. Titik koma berada pada level yang sama dengan tag <a>, tetapi huruf “C” yang ditemukan lebih dulu.

Atribut .previous_element adalah kebalikan dari .next_element. Ini menunjuk ke elemen apa pun yang diurai segera sebelum yang ini.

>>> 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 dan .previous_elements

Kami menggunakan iterator ini untuk bergerak maju dan mundur ke sebuah elemen.

>>> 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'