Beautiful Soup - การนำทางโดยแท็ก

ในบทนี้เราจะพูดถึงการนำทางด้วยแท็ก

ด้านล่างนี้คือเอกสาร html ของเรา -

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

จากเอกสารข้างต้นเราจะพยายามย้ายจากส่วนหนึ่งของเอกสารไปยังอีกส่วนหนึ่ง

กำลังลงไป

องค์ประกอบที่สำคัญอย่างหนึ่งในเอกสาร HTML คือแท็กซึ่งอาจมีแท็ก / สตริงอื่น ๆ (แท็กย่อย) Beautiful Soup นำเสนอวิธีต่างๆในการนำทางและวนซ้ำเด็ก ๆ ของแท็ก

การนำทางโดยใช้ชื่อแท็ก

วิธีที่ง่ายที่สุดในการค้นหาโครงสร้างการแยกวิเคราะห์คือการค้นหาแท็กด้วยชื่อ หากคุณต้องการแท็ก <head> ให้ใช้ soup.head -

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

เพื่อรับแท็กเฉพาะ (เช่นแท็ก <b> แรก) ในแท็ก <body>

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

การใช้ชื่อแท็กเป็นแอตทริบิวต์จะทำให้คุณมีแท็กแรกตามชื่อนั้นเท่านั้น -

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

ในการรับแอตทริบิวต์ของแท็กทั้งหมดคุณสามารถใช้ 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 และ. children

เราสามารถค้นหาลูกของแท็กในรายการตาม. เนื้อหา -

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

วัตถุ BeautifulSoup เองก็มีลูก ในกรณีนี้แท็ก <html> คือลูกของออบเจ็กต์ BeautifulSoup -

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

สตริงไม่มี. เนื้อหาเนื่องจากไม่มีอะไรเลย -

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

แทนที่จะรับเป็นรายการให้ใช้. children generator เพื่อเข้าถึงแท็กลูก ๆ -

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

. ผู้มีอำนาจ

แอตทริบิวต์. descendants ช่วยให้คุณทำซ้ำบนแท็กย่อย ๆ ทั้งหมดแบบวนซ้ำ -

ลูกโดยตรงและลูกของลูกโดยตรงและอื่น ๆ -

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

แท็ก <head> มีลูกเดียว แต่มีลูกหลานสองตัวคือแท็ก <title> และแท็กลูกของแท็ก <title> วัตถุ beautifulsoup มีลูกโดยตรงเพียงคนเดียว (แท็ก <html>) แต่มีลูกหลานจำนวนมาก -

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

.string

หากแท็กมีชายด์เพียงคนเดียวและชายด์นั้นคือ NavigableString ลูกนั้นจะพร้อมใช้งานเป็น. สตริง -

>>> Ttag.string
'Tutorials Point'

หากแท็กลูกเดียวของแท็กเป็นแท็กอื่นและแท็กนั้นมี. string แท็กหลักจะถือว่ามี. สตริงเหมือนกับแท็กระดับล่าง -

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

อย่างไรก็ตามหากแท็กมีมากกว่าหนึ่งสิ่งก็ไม่ชัดเจนว่า. สตริงควรอ้างถึงอะไรดังนั้น. สตริงจึงถูกกำหนดให้เป็นไม่มี -

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

.strings และ stripped_strings

หากมีมากกว่าหนึ่งสิ่งในแท็กคุณยังดูแค่สตริงได้ ใช้ตัวสร้าง. string -

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

หากต้องการลบช่องว่างเพิ่มเติมให้ใช้ตัวสร้าง. 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'

กำลังขึ้นไป

ในการเปรียบเทียบแบบ "แผนผังครอบครัว" ทุกแท็กและทุกสตริงจะมีพาเรนต์: แท็กที่มี:

.parent

ในการเข้าถึงองค์ประกอบหลักขององค์ประกอบให้ใช้แอตทริบิวต์ .parent

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

ใน html_doc ของเราสตริงหัวเรื่องเองก็มีพาเรนต์: แท็ก <title> ที่มีมัน −

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

ระดับบนสุดของแท็กระดับบนสุดเช่น <html> คือออบเจ็กต์ Beautifulsoup เอง -

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

.parent ของวัตถุ Beautifulsoup ถูกกำหนดให้เป็นไม่มี -

>>> print(soup.parent)
None

.parents

หากต้องการวนซ้ำองค์ประกอบพาเรนต์ทั้งหมดให้ใช้แอตทริบิวต์ .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]

ไปด้านข้าง

ด้านล่างนี้เป็นเอกสารง่ายๆ -

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

ในเอกสารด้านบนแท็ก <b> และ <c> อยู่ในระดับเดียวกันและทั้งสองเป็นแท็กลูกของแท็กเดียวกัน ทั้ง <b> และ <c> แท็กเป็นพี่น้องกัน

.next_sibling และ .previous_sibling

ใช้. next_sibling และ. Previous_sibling เพื่อนำทางระหว่างองค์ประกอบของเพจที่อยู่ในระดับเดียวกันของโครงสร้างการแยกวิเคราะห์:

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

แท็ก <b> มี. next_sibling แต่ไม่มี. previous_sibling เนื่องจากไม่มีอะไรอยู่ข้างหน้า <b> แท็กที่อยู่ในระดับเดียวกันของต้นไม้จึงมีกรณีเดียวกันกับแท็ก <c>

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

สายอักขระทั้งสองไม่ใช่พี่น้องเนื่องจากไม่มีผู้ปกครองคนเดียวกัน

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

.next_siblings และ. Previous_siblings

ในการวนซ้ำพี่น้องของแท็กให้ใช้. next_siblings และ. 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'

ไปๆมาๆ

ตอนนี้ให้เรากลับไปที่สองบรรทัดแรกในตัวอย่าง "html_doc" ก่อนหน้าของเรา -

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

โปรแกรมแยกวิเคราะห์ HTML รับสตริงอักขระเหนือสตริงและเปลี่ยนเป็นชุดของเหตุการณ์เช่น "เปิดแท็ก <html>" "เปิดแท็ก <head>" "เปิดแท็ก <title>" "เพิ่มสตริง" “ ปิดแท็ก </title>”“ ปิดแท็ก </head>”“ เปิดแท็ก <h4>” และอื่น ๆ BeautifulSoup นำเสนอวิธีการต่างๆในการสร้างการแยกวิเคราะห์เบื้องต้นของเอกสาร

.next_element และ. Previous_element

แอตทริบิวต์. next_element ของแท็กหรือสตริงชี้ไปที่สิ่งที่ถูกแยกวิเคราะห์ทันทีหลังจากนั้น บางครั้งอาจมีลักษณะคล้ายกับ. next_sibling แต่ก็ไม่เหมือนกันทั้งหมด ด้านล่างนี้คือแท็ก <a> สุดท้ายในเอกสารตัวอย่าง“ 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.'

อย่างไรก็ตาม. next_element ของแท็ก <a> นั้นสิ่งที่แยกวิเคราะห์ทันทีหลังแท็ก <a> ไม่ใช่ส่วนที่เหลือของประโยคนั้นคือคำว่า“ C”:

>>> last_a_tag.next_element
'C'

พฤติกรรมข้างต้นเป็นเพราะในมาร์กอัปดั้งเดิมตัวอักษร“ C” ปรากฏก่อนอัฒภาคนั้น โปรแกรมแยกวิเคราะห์พบแท็ก <a> ตามด้วยตัวอักษร“ C” ตามด้วยแท็กปิด </a> ตามด้วยอัฒภาคและส่วนที่เหลือของประโยค อัฒภาคอยู่ในระดับเดียวกับแท็ก <a> แต่พบตัวอักษร“ C” ก่อน

แอตทริบิวต์. Previous_element ตรงข้ามกับ. next_element ชี้ไปที่องค์ประกอบใด ๆ ที่ถูกแยกวิเคราะห์ทันทีก่อนหน้านี้

>>> 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 และ. Previous_elements

เราใช้ตัวทำซ้ำเหล่านี้เพื่อเลื่อนไปข้างหน้าและข้างหลังไปยังองค์ประกอบ

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