Beautiful Soup - 搜索树



在本章中,我们将讨论 Beautiful Soup 中用于在不同方向导航 HTML 文档树的不同方法 - 上下、左右和来回。

我们将在本章的所有示例中使用以下 HTML 字符串:

html = """
<html><head><title>TutorialsPoint</title></head>
   <body>
      <p class="title"><b>Online Tutorials Library</b></p>

      <p class="story">TutorialsPoint has an excellent collection of tutorials on:
      <a href="https://tutorialspoint.com/Python" class="lang" id="link1">Python</a>,
      <a href="https://tutorialspoint.com/Java" class="lang" id="link2">Java</a> and
      <a href="https://tutorialspoint.com/PHP" class="lang" id="link3">PHP</a>;
      Enhance your Programming skills.</p>

      <p class="tutorial">...</p>
"""

所需标签的名称允许您导航解析树。例如 soup.head 将获取 <head> 元素:

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

print (soup.head.prettify())

输出

<head>
   <title>
      TutorialsPoint
   </title>
</head>

向下导航

标签可以包含字符串或其他包含在其中的标签。Tag 对象的 .contents 属性返回属于它的所有子元素的列表。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tag = soup.head 
print (list(tag.children))

输出

[<title>TutorialsPoint</title>]

返回的对象是一个列表,尽管在本例中,head 元素中只有一个子标签。

.children

.children 属性也返回标签中所有包含元素的列表。下面,body 标签中的所有元素都作为列表给出。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tag = soup.body 
print (list(tag.children))

输出

['\n', <p class="title"><b>Online Tutorials Library</b></p>, '\n', 
<p class="story">TutorialsPoint has an excellent collection of tutorials on:
<a class="lang" href="https://tutorialspoint.com/Python" id="link1">Python</a>,
<a class="lang" href="https://tutorialspoint.com/Java" id="link2">Java</a> and
<a class="lang" href="https://tutorialspoint.com/PHP" id="link3">PHP</a>;
Enhance your Programming skills.</p>, '\n', <p class="tutorial">...</p>, '\n']

您可以使用 .children 生成器迭代标签的子元素,而不是将它们作为列表获取:

示例

tag = soup.body 
for child in tag.children:
   print (child)

输出

<p class="title"><b>Online Tutorials Library</b></p>
<p class="story">TutorialsPoint has an excellent collection of tutorials on:
<a class="lang" href="https://tutorialspoint.com/Python" id="link1">Python</a>,
<a class="lang" href="https://tutorialspoint.com/Java" id="link2">Java</a> and
<a class="lang" href="https://tutorialspoint.com/PHP" id="link3">PHP</a>;
Enhance your Programming skills.</p>


<p class="tutorial">...</p>

.descendents

.contents 和 .children 属性仅考虑标签的直接子元素。.descendants 属性允许您递归地迭代标签的所有子元素:它的直接子元素、其直接子元素的子元素,依此类推。

BeautifulSoup 对象位于所有标签层次结构的顶部。因此,它的 .descendents 属性包含 HTML 字符串中的所有元素。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

print (soup.descendants)

.descendents 属性返回一个生成器,可以使用 for 循环迭代。这里,我们列出 head 标签的后代。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')
tag = soup.head
for element in tag.descendants:
   print (element)

输出

<title>TutorialsPoint</title>
TutorialsPoint

head 标签包含一个 title 标签,该标签又包含一个 NavigableString 对象 TutorialsPoint。<head> 标签只有一个子元素,但它有两个后代:<title> 标签和 <title> 标签的子元素。但是 BeautifulSoup 对象只有一个直接子元素(<html> 标签),但它有许多后代。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tags = list(soup.descendants)
print (len(tags))

输出

27

向上导航

就像您使用 children 和 descendents 属性导航文档的下游一样,BeautifulSoup 提供了 .parent 和 .parent 属性来导航标签的上游

.parent

每个标签和每个字符串都有一个包含它的父标签。您可以使用 parent 属性访问元素的父元素。在我们的示例中,<head> 标签是 <title> 标签的父元素。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tag = soup.title
print (tag.parent)

输出

<head><title>TutorialsPoint</title></head>

由于 title 标签包含一个字符串(NavigableString),因此字符串的父元素是 title 标签本身。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tag = soup.title
string = tag.string
print (string.parent)

输出

<title>TutorialsPoint</title>

.parents

您可以使用 .parents 迭代元素的所有父元素。此示例使用 .parents 从文档深处隐藏的 <a> 标签一直遍历到文档的顶部。在以下代码中,我们跟踪示例 HTML 字符串中第一个 <a> 标签的父元素。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tag = soup.a 
print (tag.string)

for parent in tag.parents:
   print (parent.name)

输出

Python
p
body
html
[document]

横向导航

出现在相同缩进级别的 HTML 标签称为同级。考虑以下 HTML 代码片段

<p>
   <b>
      Hello
   </b>
   <i>
      Python
   </i>
</p>

在外部 <p> 标签中,我们在相同的缩进级别有 <b> 和 <i> 标签,因此它们被称为同级。BeautifulSoup 使在相同级别的标签之间导航成为可能。

.next_sibling 和 .previous_sibling

这些属性分别返回相同级别上的下一个标签和相同级别上的上一个标签。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup("<p><b>Hello</b><i>Python</i></p>", 'html.parser')

tag1 = soup.b 
print ("next:",tag1.next_sibling)

tag2 = soup.i 
print ("previous:",tag2.previous_sibling)

输出

next: <i>Python</i>
previous: <b>Hello</b>

由于 <b> 标签左侧没有同级,<i> 标签右侧没有同级,因此在这两种情况下它都返回 Nobe。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup("<p><b>Hello</b><i>Python</i></p>", 'html.parser')

tag1 = soup.b 
print ("next:",tag1.previous_sibling)

tag2 = soup.i 
print ("previous:",tag2.next_sibling)

输出

next: None
previous: None

.next_siblings 和 .previous_siblings

如果标签右侧或左侧有两个或多个同级,则可以使用 .next_siblings 和 .previous_siblings 属性分别导航它们。它们都返回生成器对象,以便可以使用 for 循环进行迭代。

让我们为此目的使用以下 HTML 代码片段:

<p>
   <b>
      Excellent
   </b>
   <i>
      Python
   </i>
   <u>
      Tutorial
   </u>
</p>

使用以下代码遍历下一个和上一个同级标签。

示例

from bs4 import BeautifulSoup

soup = BeautifulSoup("<p><b>Excellent</b><i>Python</i><u>Tutorial</u></p>", 'html.parser')

tag1 = soup.b 
print ("next siblings:")
for tag in tag1.next_siblings:
   print (tag)
print ("previous siblings:")
tag2 = soup.u 
for tag in tag2.previous_siblings:
   print (tag)

输出

next siblings:
<i>Python</i>
<u>Tutorial</u>
previous siblings:
<i>Python</i>
<b>Excellent</b>

来回导航

在 Beautiful Soup 中,next_element 属性返回解析树中的下一个字符串或标签。另一方面,previous_element 属性返回解析树中的上一个字符串或标签。有时,next_element 和 previous_element 属性的返回值与 next_sibling 和 previous_sibling 属性相似。

.next_element 和 .previous_element

示例

html = """
<html><head><title>TutorialsPoint</title></head>
<body>
<p class="title"><b>Online Tutorials Library</b></p>

<p class="story">TutorialsPoint has an excellent collection of tutorials on:
<a href="https://tutorialspoint.com/Python" class="lang" id="link1">Python</a>,
<a href="https://tutorialspoint.com/Java" class="lang" id="link2">Java</a> and
<a href="https://tutorialspoint.com/PHP" class="lang" id="link3">PHP</a>;
Enhance your Programming skills.</p>

<p class="tutorial">...</p>
"""

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

tag = soup.find("a", id="link3")
print (tag.next_element)

tag = soup.find("a", id="link1")
print (tag.previous_element)

输出

PHP
TutorialsPoint has an excellent collection of tutorials on:

id 为 "link3" 的 <a> 标签之后的 next_element 是字符串 PHP。同样,previous_element 返回 id 为 "link1" 的 <a> 标签之前的字符串。

.next_elements 和 .previous_elements

Tag 对象的这些属性分别返回其后和之前的所有标签和字符串的生成器。

Next elements 示例

tag = soup.find("a", id="link1")
for element in tag.next_elements:
   print (element)

输出

Python
,

<a class="lang" href="https://tutorialspoint.com/Java" id="link2">Java</a>
Java
 and

<a class="lang" href="https://tutorialspoint.com/PHP" id="link3">PHP</a>
PHP
;
Enhance your Programming skills.


<p class="tutorial">...</p>
...

Previous elements 示例

tag = soup.find("body")
for element in tag.previous_elements:
   print (element)

输出

<html><head><title>TutorialsPoint</title></head>
广告

© . All rights reserved.