正则表达式的使用容易理解,但是要求匹配的的语法精度高,在匹配时,不能出现一点错误,如果错误就会匹配失败。我自己在写爬虫的时候就出现的这样的情况,一个关于爬取猫眼电影的爬虫,爬取的内容不多不少:
后面找到了一个笨方法:我匹配一个运行一次,这样能保证准确率,但是对于大型爬虫自然就不能见效了(大型爬虫我相信很少使用正则),今天介绍一个比正则强大的解析库 —— Beautiful Soup
官方解释:
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
Beautiful Soup 3 目前已经停止开发,推荐在现在的项目中使用Beautiful Soup 4,不过它已经被移植到BS4了,也就是说导入时我们需要 import bs4 。所以这里我们用的版本是 Beautiful Soup 4.3.2 (简称BS4),另外据说 BS4 对 Python3 的支持不够好,不过我用的是 Python2.7.7,如果有小伙伴用的是 Python3 版本,可以考虑下载 BS3 版本。
安装方法:
1 |
easy_install beautifulsoup4 |
1 |
pip install beautifulsoup |
另一个可供选择的解析器是纯Python实现的 html5lib , html5lib的解析方式与浏览器相同,可以选择下列方法来安装html5lib:
安装方式同上
1 |
easy_install html5lib |
1 |
pip install html5lib |
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。
官方文档:http://beautifulsoup.readthedocs.io/zh_CN/latest/
首先必须要导入 bs4 库
1 |
from bs4 import BeautifulSoup |
我们创建一个字符串,后面的例子我们便会用它来演示
html = """
The Dormouse's story
The Dormouse's story
Once upon a time there were three little sisters; and their names were
,
Lacie and
Tillie;
and they lived at the bottom of a well.
...
"""
1 |
soup = BeautifulSoup(html) |
1 |
soup = BeautifulSoup(open('index.html')) |
1 |
print soup.prettify() |
The Dormouse's story The Dormouse's story
Once upon a time there were three little sisters; and their names were , Lacie and Tillie ; and they lived at the bottom of a well.
...
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
(一)、Tag: HTML 中的一个个标签
The Dormouse's story Elsie
print soup.title #
The Dormouse's story
print soup.head #
The Dormouse's story
print soup.p #
The Dormouse's story
它查找的是在所有内容中的第一个符合要求的标签,如果要查询所有的标签,我们在后面进行介绍。
对于 Tag,它有两个重要的属性,是 name 和 attrs:
name:
1 2 3 4 |
print soup.name print soup.head.name #[document] #head |
soup 对象本身比较特殊,它的 name 即为 [document],对于其他内部标签,输出的值便为标签本身的名称。
attrs(属性):
1 2 |
print soup.p.attrs #{'class': ['title'], 'name': 'dromouse'} |
如果我们想要单独获取某个属性,可以这样,例如我们获取它的 class 叫什么
1 2 |
print soup.p['class'] #['title'] |
1 2 |
print soup.p.get('class') #['title'] |
1 2 3 |
soup.p['class']="newClass" print soup.p #<p class="newClass" name="dromouse"><b>The Dormouse's story</b></p> |
1 2 3 |
del soup.p['class'] print soup.p #<p name="dromouse"><b>The Dormouse's story</b></p> |