在使用 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>