
1.4.2 网页数据解析库
由于HTML文档本身就是结构化的文本,并且具有一定的规则,所以通过解析该结构就可以提取指定的数据,于是就有了lxml、Beautiful Soup和PyQuery等网页信息解析库,其中,lxml库具有很高的解析效率,并且支持XPath语法;Beautiful Soup库翻译成中文就是“美丽的汤”,这个奇特的名字源自于《爱丽丝梦游仙境》,可以用于从HTML或XML文件中提取数据;PyQuery库则得名于jQuery,可以使用类似jQuery的语法对网页中指定的数据进行解析。
1.lxml库
lxml库是一款高性能的HTML和XML解析器,其主要功能是解析和提取HTML或XML中的数据,并且lxml库支持XPath语法,可以快速定位特定的元素及节点信息。关于XPath的基础语法在《Python全栈开发——基础入门》一书中已经详细讲解过,这里不再赘述。
可以通过lxml.etree模块中的HTML()方法对HTML字符串进行解析,其语法格式如下:
HTML(text)
其中,参数text表示HTML字符串。
此外,HTML()方法会返回一个_Element对象,该对象具有一个xpath()方法,用于快速定位特定的元素及节点信息。
下面就以爬取百度贴吧(Python吧)中帖子的点赞次数、标题和作者名称为例,讲解如何使用lxml库进行网页数据解析,示例代码如下:


图1-21 点赞次数、文章标题和作者名称
2.Beautiful Soup库
Beautiful Soup是一个高效的网页解析库,可以从HTML或XML文件中提取数据。其最大的特点是简单易用,不必像正则表达式和XPath一样需要记住很多特定的语法,尽管那样效率会更高更直接,但是对于大多数初学网络爬虫的读者来讲,好用比高效更重要,因为爬取所需的数据才是最终的目的。
Beautiful Soup属于Python的第三方库,所以需要进行安装,只需在命令提示符中输入命令pip install beautifulsoup4。
在完成安装后,需要引入该包才可以正常使用Beautiful Soup进行编程,需要注意的是,引入的包名是bs4,而不是beautifulsoup4,示例代码如下:
#资源包\Code\chapter1\1.4\0135.py import bs4
Beautiful Soup会将HTML文档转换成一个复杂的树形结构,而其中的每个节点都是一个Python对象,该对象可分为4种,即BeautifulSoup对象、Tag对象、NavigableString对象和Comment对象。
1)BeautifulSoup对象
该对象表示HTML文档的全部内容,可以通过BeautifulSoup类创建BeautifulSoup对象,其语法格式如下:
BeautifulSoup(markup,features)
其中,参数markup表示待分析的字符串;参数features表示解析器,主要用于对HTML、XML和HTML5等进行解析,其类别如表1-11所示。
表1-11 BeautifulSoup的解析器

示例代码如下:

2)Tag对象
该对象表示HTML文档中的标签,可以通过“BeautifulSoup对象+选择器”的方式创建Tag对象,其中的选择器包括以下3种:
(1)节点选择器,当待获取节点的结构层次非常清晰时,建议使用该选择器,其使用方式如下:
beautifulsoup.tag[.tag]
其中,beautifulsoup表示BeautifulSoup对象;tag表示标签,如title、li、a等,注意,标签可以进行嵌套选择。
示例代码如下:

(2)方法选择器,当待获取节点的结构层次比较复杂时,建议使用该选择器,其包括两种常用的方法:
一是find_all()方法。该方法用于获取与节点名、属性、文本内容等相符合的所有节点,并返回一个ResultSet对象,其语法格式如下:
find_all(name,attrs,text)
其中,参数name表示节点名;参数attrs表示属性名和属性值组成的字典;参数text表示文本内容。
此外,通过对ResultSet对象进行迭代处理,可以进一步获取Tag对象。
示例代码如下:

二是find()方法。该方法用于获取与节点名、属性、文本内容等相符合的第1个节点,并返回一个Tag对象,其语法格式如下:
find(name,attrs,text)
其中,参数name表示节点名;参数attrs表示属性名和属性值组成的字典;参数text表示文本内容。
示例代码如下:

(3)CSS选择器,该选择器主要借助CSS选择器进行节点的筛选,并且需要通过BeautifulSoup对象的select()方法实现,该方法返回一个ResultSet对象,其语法格式如下:
select(selector)
其中,参数selector表示CSS选择器。
示例代码如下:

在通过上面所介绍的3个选择器获取Tag对象后,就可以通过Tag对象的相关属性和方法获取当前节点的信息,其相关属性和方法如表1-12所示。
表1-12 Tag对象的相关属性和方法

这里需要重点注意的是,节点中不仅只有Tag对象一种,还包括后面即将讲解的NavigableString对象和Comment对象,所以在处理节点之间的关系时,如子孙节点、兄弟节点等,务必注意节点中的NavigableString对象和Comment对象。
示例代码如下:

3)NavigableString对象
该对象表示HTML文档中的文本内容、换行符,以及标签中的文本内容等,可以通过“BeautifulSoup对象+string”的方式获取NavigableString对象。
示例代码如下:

4)Comment对象
该对象是一个特殊的NavigableString对象,表示包含注释的文本内容。与NavigableString对象一样,可以通过“BeautifulSoup对象+string”的方式获取Comment对象。
示例代码如下:

此外,还可以通过Beautiful Soup对节点进行动态修改,为在某些特定的场景下获取节点信息带来极大的便利。
1)删除节点
可以通过BeautifulSoup对象的decompose()方法删除Tag对象节点,其语法格式如下:
decompose()
可以通过BeautifulSoup对象的extract()方法删除Tag对象节点、NavigableString对象节点或Comment对象节点,其语法格式如下:
extract()
示例代码如下:

2)添加节点
首先,需要使用BeautifulSoup对象的相关方法生成一个新的节点,其常用的方法如下:
(1)new_tag()方法,该方法用于生成Tag对象节点,其语法格式如下:
new_tag(name,**kwattrs)
其中,参数name表示标签名;参数kwattrs表示属性名和属性值所组成的字典。
(2)new_string()方法,该方法用于生成NavigableString对象节点,其语法格式如下:
new_string(s)
其中,参数s表示文本内容。
其次,在生成新的节点后,通过该节点的相关方法进行添加,其常用的方法如下:
(1)append()方法,该方法表示在当前节点的末尾添加节点,其语法格式如下:
append(tag)
其中,参数tag表示节点。
(2)insert()方法,该方法表示在当前节点的指定位置添加节点,其语法格式如下:
insert(position,new_child)
其中,参数position表示添加的位置;参数new_child表示节点。
(3)insert_before()方法,该方法表示在当前节点前添加节点,其语法格式如下:
insert_before(new_child)
其中,参数new_child表示节点。
(4)insert_after()方法,该方法表示在当前节点后添加节点,其语法格式如下:
insert_after(new_child)
其中,参数new_child表示节点。
示例代码如下:

3)修改节点文本内容
可以通过节点的属性string对文本内容进行修改,其语法格式如下:
string
示例代码如下:

4)删除节点文本内容
可以通过节点的clear()方法对文本内容进行删除,其语法格式如下:
clear()
示例代码如下:

5)修改节点属性
可以通过“节点[属性名]”的形式修改节点的属性,示例代码如下:

6)删除节点属性
可以通过del语句删除节点的属性,示例代码如下:

7)替换节点
可以通过节点的replace_with()方法对当前节点进行替换,其语法格式如下:
replace_with(replace_with)
其中,参数replace_with表示HTML字符串或节点,示例代码如下:

3.PyQuery库
具有Web前端开发经验的程序员都知道jQuery选择器的功能要强于CSS选择器,因此,虽然Beautiful Soup的功能非常强大,但是其CSS选择器的功能相对较弱,而此时PyQuery库就是绝佳选择了。PyQuery库同样是一个非常强大且灵活的网页解析库,是仿照jQuery语法封装成的一个包,其语法与jQuery几乎完全相同,可以用于网页数据的解析。
PyQuery库属于Python的第三方库,所以需要进行安装,只需在命令提示符中输入命令pip install pyquery。
1)解析HTML
在使用PyQuery库提取指定节点的信息前,首先需要使用pyquery模块中的PyQuery类对HTML数据进行解析,解析后的每个节点都是一个PyQuery对象,并且通过对该对象进行迭代,即可获取一个HtmlElement对象。
PyQuery类可以解析以下3种格式的HTML数据:
(1)HTML字符串,该格式可以使用HTML字符串作为参数进行解析,其语法格式如下:
PyQuery(html_str)
其中,参数html_str表示HTML字符串,示例代码如下:

(2)URL,该格式可以使用URL作为参数进行解析,其语法格式如下:
PyQuery(html_url)
其中,参数html_url表示URL,示例代码如下:
#资源包\Code\chapter1\1.4\0152.py from pyquery import PyQuery as pq pq_obj=pq(url='http://www.oldxia.com') print(pq_obj) print(type(pq_obj))
(3)HTML文件,该格式可以使用HTML文件作为参数进行解析,其语法格式如下:
PyQuery(filename)
其中,参数filename表示HTML文件的名称,示例代码如下:
#资源包\Code\chapter1\1.4\01\0153.py from pyquery import PyQuery as pq pq_obj=pq(filename='index.html') print(pq_obj) print(type(pq_obj))
2)获取节点
在使用PyQuery类对HTML数据进行解析后,可以通过“PyQuery对象+选择器”的方式获取指定的节点,其中选择器包括以下3种:
(1)节点选择器,当需要获取节点的结构层次非常清晰时,建议使用该种选择器,其使用方式如下:
pyquery(tag)
其中,pyquery表示PyQuery对象;tag表示标签,如title、li、a等,注意,标签可以进行嵌套选择,示例代码如下:

(2)jQuery选择器,该选择器主要借助jQuery选择器进行节点的筛选,其使用方式如下:
pyquery(selector)
其中,pyquery表示PyQuery对象;selector表示jQuery选择器,示例代码如下:

(3)方法选择器,当需要获取节点的结构层次比较复杂时,建议使用该选择器,其包括以下5种常用的方法:
一是find()方法,该方法用于获取符合条件的所有节点,其语法格式如下:
find(selector)
其中,参数selector表示节点选择器或jQuery选择器。
二是children()方法,该方法用于获取符合条件的所有直接子节点,其语法格式如下:
children(selector)
其中,参数selector为可选参数,表示节点选择器或jQuery选择器,默认表示无条件。
三是parent()方法,该方法用于获取符合条件的直接父节点,其语法格式如下:
parent(selector)
其中,参数selector为可选参数,表示节点选择器或jQuery选择器,默认表示无条件。
四是parents()方法,该方法用于获取符合条件的所有祖先节点,其语法格式如下:
parents(selector)
其中,参数selector为可选参数,表示节点选择器或jQuery选择器,默认表示无条件。
五是siblings()方法,该方法用于获取符合条件的所有兄弟节点,其语法格式如下:
siblings(selector)
其中,参数selector为可选参数,表示节点选择器或jQuery选择器,默认表示无条件。
示例代码如下:

3)获取节点信息
在获取节点后,可以通过HtmlElement对象或PyQuery对象的相关属性和方法提取节点的信息。
(1)HtmlElement对象,通过对PyQuery对象进行迭代或使用索引方式就可以得到HtmlElement对象,其相关属性和方法如表1-13所示。
表1-13 HtmlElement对象的相关属性和方法

示例代码如下:

(2)PyQuery对象,该对象的相关方法如表1-14所示。
表1-14 PyQuery对象的相关方法

此外,由于对PyQuery对象进行迭代所获得的是HtmlElement对象,所以如果想通过迭代获得PyQuery对象,则需要使用PyQuery对象的items()方法,示例代码如下:

4)修改节点
可以通过PyQuery对节点进行动态修改,为在某些特定的场景下获取节点信息带来极大的便利。
(1)删除节点,可以通过PyQuery对象的remove()方法删除节点,其语法格式如下:
remove(expr)
其中,参数expr为可选参数,表示节点选择器或jQuery选择器,默认表示无条件,示例代码如下:

(2)添加节点,可以通过PyQuery对象的prepend()方法或append()方法分别在头部或尾部添加节点,其语法格式分别如下:
prepend(value)
其中,参数value表示HTML字符串。
append(value)
其中,参数value表示HTML字符串。
示例代码如下:

(3)修改节点属性,可以通过PyQuery对象的attr()方法修改节点属性,其语法格式如下:
attr(attr,value)
其中,参数attr表示属性名称;参数value表示属性值,示例代码如下:

(4)删除节点属性,可以通过PyQuery对象的remove_attr()方法删除节点属性,其语法格式如下:
remove_attr(name)
其中,参数name表示属性名称,示例代码如下:

(5)修改节点文本内容,可以通过PyQuery对象的text()方法或html()方法修改节点的文本内容,其语法格式分别如下:
text(value)
其中,参数value表示文本内容。
html(value)
其中,参数value表示文本内容。
示例代码如下:

(6)添加节点样式,可以通过PyQuery对象的add_class()方法添加节点样式,其语法格式如下:
add_class(value)
其中,参数value表示属性class的属性值,示例代码如下:

(7)删除节点样式,可以通过PyQuery对象的remove_class()方法删除节点样式,其语法格式如下:
remove_class(value)
其中,参数value表示属性class的属性值,示例代码如下:
