Python全栈开发:数据分析
上QQ阅读APP看书,第一时间看更新

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的属性值,示例代码如下: