上一节我们介绍了正则表达式,它的内容其实还是蛮多的,如果一个正则匹配稍有差池,那可能程序就处在永久的循环之中,而且有的小伙伴们也对写正则表达式的写法用得不熟练,没关系,我们还有一个更强大的工具,叫 Beautiful Soup,有了它我们可以很方便地提取出 HTML 或 XML 标签中的内容,实在是方便,这一节就让我们一起来感受一下 Beautiful Soup 的强大吧。
1. Beautiful Soup 的简介
简单来说,Beautiful Soup 是 python 的一个库,最主要的功能是从网页抓取数据。官方解释如下:
Beautiful Soup 提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。 Beautiful Soup 自动将输入文档转换为 Unicode 编码,输出文档转换为 utf-8 编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup 就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。 Beautiful Soup 已成为和 lxml、html6lib 一样出色的 python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。
废话不多说,我们来试一下吧~
2. Beautiful Soup 安装
Beautiful Soup 3 目前已经停止开发,推荐在现在的项目中使用 Beautiful Soup 4,不过它已经被移植到 BS4 了,也就是说导入时我们需要 import bs4 。所以这里我们用的版本是 Beautiful Soup 4.3.2 (简称 BS4),另外据说 BS4 对 Python3 的支持不够好,不过我用的是 Python2.7.7,如果有小伙伴用的是 Python3 版本,可以考虑下载 BS3 版本。 可以利用 pip 或者 easy_install 来安装,以下两种方法均可
1 |
easy_install beautifulsoup4 |
1 |
pip install beautifulsoup4 |
如果想安装最新的版本,请直接下载安装包来手动安装,也是十分方便的方法。在这里我安装的是 Beautiful Soup 4.3.2 Beautiful Soup 3.2.1Beautiful Soup 4.3.2 下载完成之后解压 运行下面的命令即可完成安装
1 |
sudo python setup.py install |
然后需要安装 lxml
1 |
easy_install lxml |
1 |
pip install lxml |
另一个可供选择的解析器是纯 Python 实现的 html5lib , html5lib 的解析方式与浏览器相同,可以选择下列方法来安装 html5lib:
1 |
easy_install html5lib |
1 |
pip install html5lib |
Beautiful Soup 支持 Python 标准库中的 HTML 解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python 默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。
<thead”>
解析器
使用方法
优势
劣势
Python 标准库
BeautifulSoup(markup, “html.parser”)
- Python 的内置标准库
- 执行速度适中
-
文档容错能力强
-
Python 2.7.3 or 3.2.2) 前 的版本中文档容错能力差
lxml HTML 解析器
BeautifulSoup(markup, “lxml”)
- 速度快
-
文档容错能力强
-
需要安装 C 语言库
lxml XML 解析器
BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”)
- 速度快
-
唯一支持 XML 的解析器
-
需要安装 C 语言库
html5lib
BeautifulSoup(markup, “html5lib”)
- 最好的容错性
- 以浏览器的方式解析文档
-
生成 HTML5 格式的文档
-
速度慢
- 不依赖外部扩展
3. 开启 Beautiful Soup 之旅
在这里先分享官方文档链接,不过内容是有些多,也不够条理,在此本文章做一下整理方便大家参考。 官方文档
4. 创建 Beautiful Soup 对象
首先必须要导入 bs4 库
1 |
from bs4 import BeautifulSoup |
我们创建一个字符串,后面的例子我们便会用它来演示
1 2 3 4 5 6 7 8 9 10 11 |
html = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ |
创建 beautifulsoup 对象
1 |
soup = BeautifulSoup(html) |
另外,我们还可以用本地 HTML 文件来创建对象,例如
1 |
soup = BeautifulSoup(open('index.html')) |
上面这句代码便是将本地 index.html 文件打开,用它来创建 soup 对象 下面我们来打印一下 soup 对象的内容,格式化输出
1 |
print soup.prettify() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<html> <head> <title> The Dormouse's story </title> </head> <body> <p class="title" name="dromouse"> <b> The Dormouse's story </b> </p> <p class="story"> Once upon a time there were three little sisters; and their names were <a class="sister" href="http://example.com/elsie" id="link1"> <!-- Elsie --> </a> , <a class="sister" href="http://example.com/lacie" id="link2"> Lacie </a> and <a class="sister" href="http://example.com/tillie" id="link3"> Tillie </a> ; and they lived at the bottom of a well. </p> <p class="story"> ... </p> </body> </html> |
以上便是输出结果,格式化打印出了它的内容,这个函数经常用到,小伙伴们要记好咯。
5. 四大对象种类
Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构,每个节点都是 Python 对象,所有对象可以归纳为 4 种:
- Tag
- NavigableString
- BeautifulSoup
- Comment
下面我们进行一一介绍
(1)Tag
Tag 是什么?通俗点讲就是 HTML 中的一个个标签,例如
1 |
<title>The Dormouse's story</title> |
1 |
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> |
上面的 title a 等等 HTML 标签加上里面包括的内容就是 Tag,下面我们来感受一下怎样用 Beautiful Soup 来方便地获取 Tags 下面每一段代码中注释部分即为运行结果
1 2 |
print soup.title #<title>The Dormouse's story</title> |
1 2 |
print soup.head #<head><title>The Dormouse's story</title></head> |
1 2 |
print soup.a #<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a> |
1 2 |
print soup.p #<p class="title" name="dromouse"><b>The Dormouse's story</b></p> |
我们可以利用 soup 加标签名轻松地获取这些标签的内容,是不是感觉比正则表达式方便多了?不过有一点是,它查找的是在所有内容中的第一个符合要求的标签,如果要查询所有的标签,我们在后面进行介绍。 我们可以验证一下这些对象的类型
1 2 |
print type(soup.a) #<class 'bs4.element.Tag'> |
对于 Tag,它有两个重要的属性,是 name 和 attrs,下面我们分别来感受一下 name
1 2 3 4 |
print soup.name print soup.head.name #[document] #head |
soup 对象本身比较特殊,它的 name 即为 [document],对于其他内部标签,输出的值便为标签本身的名称。 attrs
1 2 |
|