本文为北理嵩天老师《Python网络爬虫与信息提取》学习笔记。
Beautiful Soup库能够对提供给它的任何格式进行爬取,并且进行属性解析。在爬虫中,常被用来解析html和xml页面。
Beautiful Soup库是解析、遍历、维护“标签树”的功能库。
一个html文档是由标签树构成的,下面两张图分别是链接https://python123.io/ws/demo.html对应的html页面和网页源码:
该网页源码所对应的标签树如下图:
通常认为html文档、标签树、BeautifulSoup类、三者是等价的关系。
import requests
from bs4 import BeautifulSoup #(从bs4库导入BeautifulSoup类
url="https://python123.io/ws/demo.html"
r=requests.get(url)
demo=r.text
soup=BeautifulSoup(demo,"html.parser")
BeautifulSoup()函数有两个主要的参数:
(1)demo: 需要解析的代码信息,为字符串类型。例如代码中的url所对应的网页源代码。
(2)“html.parser”: 是对demo进行解析的解析器,这里指对其进行html的解析。
除"html.parser"解析器外,Python还提供了另外三个解析器,使用它们,需要安装第三方库
print(soup.title) #获取标题标签的内容
print(soup.a) #获取链接标签的内容
(2)获取标签的名字
print(soup.a.name) #获取a标签的名字
print(soup.a.parent.name) #获取a标签的父标签的名字
print(soup.a.parent.parent.name) #获取a标签父标签的父亲标签名字
(3)获取标签的属性
tag=soup.a
print(tag.attrs) #获取标签的属性
print(tag.attrs['class']) #获取a标签class属性的值
print(tag.attrs['href']) #获取a标签的链接属性属性的值
标签的属性:是标明标签特点的相关区,常以字典的形式来组成。由于是字典,还可采用字典的方式对每一个属性进行信息的提取。
还可查看标签属性的类型:
print(type(tag)) #查看标签的类型
在bs4库中,将标签定义成了bs4.element.Tag类型。
(4)查看标签的NavigableString属性
print(soup.a.string) #查看标签a的NavigableString属性
print(soup.p.string) #查看标签p的NavigableString属性
默认得到的是第一个a标签或p标签的相关信息。
输出结果如下图:
查看网页源代码不难发现,p标签的内部其实还含有一个b标签:
但输出直接跨过b标签,说明NavigableString是可以跨越多个标签层次的。
HTML树形结构有三种遍历方法:下行遍历、上行遍历、平行遍历。
(1)下行遍历
从根节点到叶子节点的遍历。
print(soup.head)
print(soup.head.contents) #遍历soup.head的子节点
print(soup.body.contents)
print(len(soup.body.contents)) #使用len函数获得儿子节点的数量
print(soup.body.contents[1]) #使用列表类型的下标来查看body的相关子节点
for child in soup.body.children:
print(child)
for child in soup.body.descendants:
print(child)
.children和.descendants返回的是迭代器类型,可以for…in…的循环结构进行查看。
''' 上行遍历 '''
print(soup.title.parent) #查看title标签的父亲标签
print(soup.html.parent) #html标签是html的最上层结构,其父标签为它本身
print(soup.parent) #soup的父标签为空
'''标签树的上行遍历'''
#在遍历一个标签的所有先辈标签时,会遍历到soup本身,而soup的先辈标签并不存在,所以需要用if语句做一个区分
for parent in soup.a.parents:
if parent is None:
print(parent)
else:
print(parent.name)
在遍历一个标签的所有先辈标签时,会遍历到soup本身,而soup的先辈标签并不存在,所以需要用if语句做一个区分。
(3)平行遍历
在平行节点之间互相遍历的方式。
标签树的平行遍历必须是发生在同一个父节点下的各个节点间。
'''平行遍历'''
print(soup.a.next_sibling) #查看标签a的下一个平行节点标签
print(soup.a.next_sibling.next_sibling) #查看标签a的下一个平行节点标签的下一个平行节点标签
输出结果为:
在标签树中,尽管树形结构采用的是标签的形式来进行组织,但是标签中的NavigableString也构成了标签树的节点。即任何一个节点,它的平行标签、儿子标签是可能存在NavigableString类型的。所以平行遍历获得的下一个节点不一定是标签类型。
for sibling in soup.a.next_siblings: #遍历后续平行节点
print(sibling)
for sibling in soup.a.previous_siblings: #遍历前续平行节点
print(sibling)
bs4库中的prettify()方法能让html页面更加友好的显示。
prettify()方法可以为html文本增加换行符,也可对每对标签做相关的处理。
print(soup.prettify())
其输出结果让我们更易于理解html标签树的层次:
另外:
bs4库将任何读入的html文件和字符串utf-8编码(支持中文)。
python3.x版本默认支持utf-8。