在使用 lxml 库解析网页数据时,每次都需要编写和测试 XPath 的路径表达式,显得非常
烦琐。为了解决这个问题, Python 还提供了 Beautiful Soup 库提取 HTML 文档或 XML 文档的
节点。 Beautiful Soup 使用起来很便捷,受到了开发人员的推崇。接下来,本节先带领大家认
识 Beautiful Soup ,再为大家介绍如何使用 Beautiful Soup 解析网页数据。
一、Beautiful Soup 简介
Beautiful Soup 是一个用于从 HTML 文档或 XML 文档中提取目标数据的 Python 库。它历
经了众多版本,其中 Beautiful Soup 3 已经停止开发与维护,官方推荐使用 Beautiful Soup 4 (简
称 bs4 )进行程序开发。截至本书完稿时, Beautiful Soup 的最新版本是 4.4.0 。
为了快速解析 HTML 文档或 XML 文档的数据, bs4 不仅提供了多种类型的解析器,还支
持 CSS 选择器。 bs4 通过解析器可以将 HTML 或 XML 文档、片段转换成节点树,节点树中
的每个节点对应一个 Python 类的对象。 bs4 库或 bs4.element 模块中提供了 Tag 类、
NavigableString 类、 BeautifulSoup 类、 Comment 类等 4 个比较重要的类。关于这 4 个类的具
体介绍如下。
- bs4.element.Tag 类:表示 HTML 或 XML 中的元素,是最基本的信息组织单元。它有 两个非常重要的属性:表示元素名称的 name 和表示元素属性的 attrs。
- bs4.element.NavigableString 类:表示 HTML 或 XML 元素中的文本(非属性字符串)。
- bs4.BeautifulSoup 类:表示 HTML 或 XML 节点树中的全部内容,支持遍历节点树和 搜索节点树的大部分方法。
- bs4.element.Comment类:表示元素内字符串的注释部分,是一种特殊的NavigableString 类的对象。
bs4 的用法非常简单,一般分为如下 3 个步骤。
( 1 )根据 HTML 或 XML 文档、片段创建 BeautifulSoup 类的对象。
( 2 )通过 BeautifulSoup 类的对象的查找方法或 CSS 选择器定位节点。
( 3 )通过访问节点的属性或节点的名称提取文本。
二、创建 BeautifulSoup 类的对象
要想使用 bs4 解析网页数据,需要先使用构造方法创建 BeautifulSoup 类的对象。
BeautifulSoup 类的构造方法的声明如下。
BeautifulSoup(markup="", features=None, builder=None, parse_only=None, from_encoding=None, exclude_encodings=None, element_classes=None, **kwargs)
上述方法中常用参数的含义如下。
- markup:必选参数,表示待解析的内容,可以取值为字符串或类似文件的对象。
- features:可选参数,表示指定的解析器。该参数可以接收解析器名称或标记类型。其 中,解析器名称包括 lxml、lxml-xml、html.parser 和 html5lib,标记类型包括 html、html5 和 xml。
- parse_only:可选参数,指定只解析部分文档。该参数需要接收一个 SoupStrainer 类的 对象。当文档太大而无法全部放入内存时,便可以考虑只解析一部分文档。
- from_encoding:可选参数,指定待解析文档的编码格式。 值得一提的是,如果我们只需要解析 HTML 文档,那么在创建 BeautifulSoup 类的对象时 可以不用指定解析器。此时 Beautiful Soup 会根据当前系统安装的库自动选择解析器。解析器 的选择顺序为 lxml→html5lib→Python 标准库,但在以下两种情况下会发生变化。
- 要解析的文档是什么类型?目前支持 html、xml 和 html5。
- 指定使用哪种解析器?目前支持 lxml、html5lib 和 html.parser。
如果指定的解析器没有安装,那么 Beautiful Soup 会自动选择其他方案。不过,目前只有
解析器 lxml 支持 XML 文档的解析。在当前系统中没有安装解析器 lxml 的情况下,即使创建
BeautifulSoup 对象时明确指定使用解析器 lxml ,也无法得到解析后的内容。
下面通过一张表来区分上述 4 种解析器的优势与劣势,具体如表 4-7 所示。
接下来,通过一个例子来演示如何创建 BeautifulSoup 类的对象,具体代码如下。
1 from bs4 import BeautifulSoup
2 html_doc = """<html><head><title>The Dormouse's story</title></head>
3 <body>
4 <p class="title"><b>The Dormouse's story</b></p>
5 <p class="story">Once upon a time there were three little sisters;
6 and their names were
7 <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
8 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
9 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
10 and they lived at the bottom of a well.</p>
11 <p class="story">...</p>
12 """
13 # 根据 html_doc 创建 BeautifulSoup 类的对象,并指定使用 lxml 解析器解析文档
14 soup = BeautifulSoup(html_doc, features='lxml')
15 print(soup.prettify())
在上述示例代码中,第 1 行代码导入了 BeautifulSoup 类,第 2 ~ 12 行定义了变量 html_doc
保存 HTML 代码片段,第 14 行代码根据 html_doc 创建了一个 BeautifulSoup 类的对象,并指
定使用解析器 lxml 来解析 HTML 文档,第 15 行代码输出了 soup.prettify() 执行的结果,其中
prettify() 方法会对 HTML 代码片段进行格式化处理,友好地显示 HTML 代码。
运行代码,输出如下结果。
<html> <head> <title> The Dormouse's story </title> </head> <body> <p class="title"> <b> The Dormouse's story </b> </p> ……</body>
</html>