返回介绍

Beautiful Soup 遍历文档树

发布于 2024-05-19 17:34:36 字数 7825 浏览 0 评论 0 收藏 0

1. 子节点

一个 Tag 可能包含多个 NaviableString 或者其他的 Tag ,这些都是这个 Tag 的子节点。 BeautifulSoup 提供了许多方法来遍历子节点。

NaviableString 没有子节点,因此无法遍历它

a. 通过 Tag 的名字遍历

操作文档树最简单的方法就是通过标签名字获取 Tag 。如果想获取 <head> 标签,只需要使用 soup.head

  • 通过 soup.a 获得的只是标签 <a></a> 的第一个标签。要像获取所有的 <a></a> 标签,必须用 find_all() 等方法
  • 可以如果想获取标签中的子标签,则可以反复使用 . 表达式,如: soup.head.body.a

通过 Tag 的名字遍历

b. 通过 Tag.contentsTag.children 遍历

Tag.contents 属性可以将 Tag 的子节点按照列表的方式输出。而通过 Tag.children 生成器,可以对 Tag 的子节点进行循环。

  • BeautifulSoup 对象也可以按照这种方式进行遍历。因为 BeautifulSoup 对象一定会包含子节点,如 <html> 标签。
  • NavigableString 对象不能按照这种方式遍历。因为它没有子节点。

    哪怕提供给 BeautifulSoup 构造函数的字符串并没有 <html></html> 标签, BeautifulSoup 也会自动构造出 <html></html> 标签。

    通过 Tag.contents 和 Tag.children 遍历

c. 通过 Tag.descendants 遍历

通过 Tag.contentsTag.children 遍历时,只能访问 Tag 的直接子节点,而无法访问到孙节点以及孙节点以下节点。 而通过 Tag.descendants 可以获取 Tag 的所有子孙节点(无论是否直系子节点),注意 Tag.descendants 是一个生成器。

  • BeautifulSoup 对象也可以按照这种方式进行遍历。因为 BeautifulSoup 对象一定会包含子节点,如 <html> 标签。
  • NavigableString 对象不能按照这种方式遍历。因为它没有子节点。

    通过 Tag.descendants 遍历

d. 通过 Tag.string 遍历

  • 如果 Tag 只有一个 NavigableString 类型的子节点,那么可以通过 Tag.string 获得该子节点。
  • 如果 Tag 只有一个 Tag 类型的子节点,那么通过 Tag.string 获取的是该子节点的 .string 的结果。
  • 如果 Tag 包含了多个子节点,那么 Tag.string 输出为 None
  • 如果 Tag 不包含任何子节点,则 Tag.string 输出为 None
    • BeautifulSoup 对象也可以按照这种方式进行遍历。因为 BeautifulSoup 对象一定会包含子节点, 如 <html> 标签。
    • NavigableString 对象不能按照这种方式遍历。因为它没有子节点。

    通过 Tag.string 遍历

e. 通过 Tag.stringsTag.stripped_strings 遍历

如果想访问 Tag 以及所有子节点(无论是否直系子节点)中的文本内容,可以使用 Tag.strings 进行循环获取。但是这种方式获取的结果可能含有大量空格或者空白行。在这种情况下可以用 Tag.stripped_strings 可以去除多余空白内容。这两个属性都返回的是生成器对象。

Tag.strings 生成器遍历时,它会读取 Tag 以及它所有子节点的文本内容,即使某个子节点没有文本 (如 <div></div> 标签),此时该子节点的文本输出为空字符串。

  • BeautifulSoup 对象也可以按照这种方式进行遍历。因为 BeautifulSoup 对象一定会包含子节点,如 <html> 标签。
  • NavigableString 对象不能按照这种方式遍历。因为它没有子节点。

    通过 Tag.strings 和 Tag.stripped_strings 遍历

2.父节点

每个 Tag 或者 NavigableString 都有父节点(某个 Tag 对象)

a. 通过 .parent 访问父节点

可以通过 Tag.parent 获取 Tag 的父节点,通过 NavigableString.parent 获取 NavigableString 的父节点。

  • 文档的顶层节点,如 <html> 的父节点是 BeautifulSoup 对象
  • BeautifulSoup 对象的父节点是 None

    通过 Tag.parent 遍历

b. 通过 .parents 访问节点

通过 Tag.parentsNavigableString.parents 可以递归得到元素的所有父辈节点。该属性返回的是一个生成器对象。

通过 Tag.parents 遍历

3. 兄弟节点

a. 通过 .next_sibling.previous_sibling 遍历

在文档树中可以通过 Tag.next_sibling 或者 NavigableString.next_sibling 来查询后一个兄弟节点;通过 Tag.previous_siblingNavigableString.previous_sibling 来查询前一个兄弟节点。

  • 第一个节点的 .previous_sibling 返回 None
  • 最后一个节点的 .next_sibling 返回 None

注意:对于 NavigableString 的兄弟节点一定是 Tag 节点或者为空,也可能是另一个 NavigableString 节点。而对于 Tag 节点的兄弟节点却不一定是 Tag 节点或者为空,因为也可能是 NavigableString 字符串节点(尤其是 HTML 显示时看起来是空白其实有换行符或者空白符的时候)。

b. 通过 .next_siblings.previous_siblings 遍历

在文档树中可以通过 Tag.previous_siblings 或者 NavigableString.previous_siblings 来迭代本节点前面的兄弟节点;通过 Tag.next_siblingsNavigableString.next_siblings 来迭代本节点后面的兄弟节点。它们都是生成器对象。

访问兄弟节点

4. 回退和前进

对于文档

	<html>
	<head><title>The Dormouse's story</title></head>
	<p class="title"><b>The Dormouse's story</b></p>
	</html>

HTML 解析器将这段字符串转换成一连串的事件:

  • 打开 <html> 标签
  • 打开 <head> 标签
  • 打开 <title> 标签
  • 添加一段字符串
  • 关闭 <title> 标签
  • 关闭 <head> 标签
  • 打开 <p> 标签
  • ....

Beautiful Soup 提供了重现这一过程的方法。

a. 通过 .next_element.previous_element 遍历

在文档树中可以通过 Tag.next_element 或者 NavigableString.next_element 来获取本节点之后下一个被解析的对象(可能是 Tag 或者 NavigableString );也可以通过 Tag.previous_element 或者 NavigableString.previous_element 来获取本节点之前上一个被解析的对象(可能是 Tag 或者 NavigableString )。

.next_element 可能与 .next_sibling 相同,也可能不同。对于 <a> txt</a><b></b> 这种 HTML 节点,标签 <a> 的下一个解析节点是 <a> 内部的字符串;标签 <a> 的下一个兄弟节点是 <b> 标签。

a. 通过 .next_elements.previous_elements 遍历

在文档树中可以通过 Tag.previous_elements 或者 NavigableString.previous_elements 来迭代本节点前面解析的节点;通过 Tag.next_elementsNavigableString.next_elements 来迭代本节点后面解析的节点。它们都是生成器对象。

访问前后解析的节点

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文