0 引言
最近学习Python网络爬虫,用到一款实战利器:BeautifulSoup,学习了BeautifulSoup的官方文档,本文以BeautifulSoup 4.4.0官方文档为基础,参考了一些其他博客内容,叙述了BeautifulSoup在网络爬虫方面的应用方法,结合自己的体会对其进行了一点总结。
1 What:BeautifulSoup是什么
BeautifulSoup是用python写的一个HTML/XML的解析器,它能够通过你喜欢的转换器实现管用的文档导航、查找、修改文档的方式。
简单点来说,BeautifulSoup就是在进行爬虫项目时识别HTML代码段并处理的一种容器。
2 How:如何使用BeautifulSoup
2.1 对象的种类
BeautifulSoup将HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,这些对象可以归纳为4种:Tag(标签)、NavigableString(可遍历字符串)、BeautifulSoup(整个文档)、Comment(注释及特殊字符串)
2.1.1 Tag——标签对象
BeautifulSoup中的Tag和XML/HTML中的Tag用法相同,其方法和属性很多,待后续介绍,本节主要介绍两个最重要的属性:name和attributes。
2.1.1.1 name属性
name属性及Tag的标签名,如HTML中的b标签、div标签等。
获取标签名的方法:tag.name
修改标签名的方法(直接赋值):tag.name = 'new_name'
2.1.1.2 attributes属性
Tag的attributes属性即Tag中包含的各种属性,例如:
tag = BeautifulSoup('<b class = "boldest">attributes</b>','html.parser').b
其中class就是Tag的一个attributes属性。对于属性其操作方法与Python字典相同:
>>> tag['class']
['boldest']`
(注意:这里返回值为一个只有一个元素的列表,这是由于class属性为多值属性,也就是说一个Tag的class属性可以有多个不同的值。多值属性后文会介绍到。如果这里是id等单值属性,则返回结果为一个字符串。)
也可以通过tag.attrs
来获取所有属性-值对,其返回值为
>>> tag.attrs
{
'class': ['boldest']}
既然Tag的属性和字典操作方法相同,自然字典一样增删修改属性内容:
>>> tag['class'] = ['verybold','bolder']
>>> tag
<b class="verybold bolder"> attributes </b>
>>> tag['id'] = '1'
>>> tag
<b class="verybold bolder" id="1"> attributes </b>
>>> del tag['class']
>>> tag
<b id="1"> attributes </b>
2.1.2 NavigableString——可遍历字符串对象
BeautifulSoup中NavigableString字符串即被包含在一个标签对中的字符串内容,可用tag.string
来获取其内容。
通常处理NavigableString时药先转换为Unicode,可以通过string = unicode(tag.string)
来实现。
NavigableString不可编辑,但可以被替换,可以通过tag.string.replace_with(”)实现,更多具体操作方法待后文叙述。
2.1.3 BeautifulSoup——整个文档对象
BeautifulSoup大部分时间可以看作Tag对象,但是没有Tag对象的attributes属性。此外,对于BeautifulSoup对象使用soup.name
属性时会返回[document]值。除以上两条外,几乎和Tag使用方式相同。
2.1.4 Comment——注释及特殊字符串对象
Comment对象是特殊的NavigableString对象,例如:
>>> markup = "<b><!--Hey, buddy, want to buy a used Parser:--></b>"
>>> soup = BeautifulSoup(markup,'html.parser')
>>> comment = soup.b.string
>>> type(comment)
<class 'bs4.element.Comment'>
>>> print(comment)
Hey, buddy, want to buy a used Parser:
>>> print(soup.b)
<b><!--Hey, buddy, want to buy a used Parser:--></b>
这里的内容仔细体会一下可以发现其中的细枝末节。
2.2 遍历文档树
2.2.1 子节点
每个Tag可能包含多个其他的Tag或者字符串,这些称谓Tag的子节点,下面介绍BeautifulSoup中操作和遍历子节点的属性,应该注意的是BeautifulSoup中的字符串节点没有子节点,因此下面一些属性是不支持的。
2.2.1.1 直接使用Tag的名字获取子节点
这里以一个例子进行介绍:
>>> text = "<head><title>The Dormouse's story</title><head>"
>>> soup = BeautifulSoup(text,'html.parser')
>>> soup.head
<head><title>The Dormouse's story</title><head></head></head>
>>> soup.title
<title>The Dormouse's story</title>
>>> soup.head.title
<title>The Dormouse's story</title>
使用soup.head
获取head子节点,用soup.title
或soup.head.title
获取title子节点。
小结:直接用Tag的名字可获取所有子孙节点中的第一个,并返回字符串,其作用结果与soup.find('tag_name')
相同。如果需要获取所有特定的子孙节点,则需要用soup.find_all('tag_name')
,其返回值为一个列表:
>>> soup.find("title")
<title>The Dormouse's story</title>
>>> soup.find_all('title')
[<title>The