Python 爬虫之Beautiful Soup模块使用指南


Posted in Python onJuly 05, 2018

爬取网页的流程一般如下:

  1. 选着要爬的网址(url)
  2. 使用 python 登录上这个网址(urlopen、requests 等)
  3. 读取网页信息(read() 出来)
  4. 将读取的信息放入 BeautifulSoup
  5. 使用 BeautifulSoup 选取 tag 信息等

可以看到,页面的获取其实不难,难的是数据的筛选,即如何获取到自己想要的数据。本文就带大家学习下 BeautifulSoup 的使用。

BeautifulSoup 官网介绍如下:

Beautiful Soup 是一个可以从 HTML 或 XML 文件中提取数据的 Python 库,它能够通过你喜欢的转换器实现惯用的文档导航、查找、修改文档的方式,能够帮你节省数小时甚至数天的工作时间。

1 安装

可以利用 pip 直接安装:

$ pip install beautifulsoup4

BeautifulSoup 不仅支持 HTML 解析器,还支持一些第三方的解析器,如 lxml,XML,html5lib 但是需要安装相应的库。如果我们不安装,则 Python 会使用 Python 默认的解析器,其中 lxml 解析器更加强大,速度更快,推荐安装。

$ pip install html5lib
$ pip install lxml

2 BeautifulSoup 的简单使用

首先我们先新建一个字符串,后面就以它来演示 BeautifulSoup 的使用。

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><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" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

使用 BeautifulSoup 解析这段代码,能够得到一个 BeautifulSoup 的对象,并能按照标准的缩进格式的结构输出:

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html_doc, "lxml")
>>> print(soup.prettify())

篇幅有限,输出结果这里不再展示。

另外,这里展示下几个简单的浏览结构化数据的方法:

>>> soup.title
<title>The Dormouse's story</title>
>>> soup.title.name
'title'
>>> soup.title.string
"The Dormouse's story"
>>> soup.p['class']
['title']
>>> soup.a
<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>
>>> soup.find_all('a')
[<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link3">Tillie</a>]
>>> soup.find(id='link1')
<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>

3 对象的种类

Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构,每个节点都是 Python 对象,所有对象可以归纳为 4 种: Tag、NavigableString、BeautifulSoup、Comment 。

3.1 Tag

Tag通俗点讲就是 HTML 中的一个个标签,像上面的 div,p,例如:

<title>The Dormouse's story</title>
  
<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>

可以利用 soup 加标签名轻松地获取这些标签的内容。

>>> print(soup.p)
<p class="title"><b>The Dormouse's story</b></p>
>>> print(soup.title)
<title>The Dormouse's story</title>

不过有一点是,它查找的是在所有内容中的第一个符合要求的标签,如果要查询所有的标签,我们在后面进行介绍。

每个 Tag 有两个重要的属性 name 和 attrs,name 指标签的名字或者 tag 本身的 name,attrs 通常指一个标签的 class。

>>> print(soup.p.name)
p
>>> print(soup.p.attrs)
{'class': ['title']}

3.2 NavigableString

NavigableString:获取标签内部的文字,如,soup.p.string。

>>> print(soup.p.string)
The Dormouse's story

3.3 BeautifulSoup

BeautifulSoup:表示一个文档的全部内容。大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag。

3.4 Comment

Comment:Comment 对象是一个特殊类型的 NavigableString 对象,其输出的内容不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。

>>> markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
>>> soup = BeautifulSoup(markup)
>>> comment = soup.b.string
>>> print(comment)
Hey, buddy. Want to buy a used parser?
>>> type(comment)
<class 'bs4.element.Comment'>

b 标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦。

这时候我们可以先判断了它的类型,是否为 bs4.element.Comment 类型,然后再进行其他操作,如打印输出等。

4 搜索文档树

BeautifulSoup 主要用来遍历子节点及子节点的属性,并提供了很多方法,比如获取 子节点、父节点、兄弟节点等,但通过实践来看,这些方法用到的并不多。我们主要用到的是从文档树中搜索出我们的目标。

通过点取属性的方式只能获得当前文档中的第一个 tag,例如,soup.li。如果想要得到所有的<li> 标签,就需要用到 find_all(),find_all() 方法搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件 find_all() 所接受的参数如下:

find_all( name , attrs , recursive , text , **kwargs )

4.1 按 name 搜索

可以查找所有名字为 name 的 tag,字符串对象会被自动忽略掉。

>>> soup.find_all('b')
[<b>The Dormouse's story</b>]
>>> soup.find_all('a')
[<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link3">Tillie</a>]

4.2 按 id 搜索

如果文档树中包含一个名字为 id 的参数,其实在搜索时会把该参数当作指定名字 tag 的属性来搜索:

>>> soup.find_all(id='link1')
[<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>]

4.3 按 attr 搜索

有些 tag 属性在搜索不能使用,比如 HTML5 中的 data-* 属性,但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的 tag。

其实 id 也是一个 attr:

>>> soup.find_all(attrs={'id':'link1'})
[<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>]

4.4 按 CSS 搜索

按照 CSS 类名搜索 tag 的功能非常实用,但标识 CSS 类名的关键字 class 在 Python 中是保留字,使用 class 做参数会导致语法错误。因此从 Beautiful Soup 的 4.1.1 版本开始,可以通过 class_ 参数搜索有指定 CSS 类名的 tag:

>>> soup.find_all(class_='sister')
[<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link3">Tillie</a>]

4.5 string 参数

通过 string 参数可以搜搜文档中的字符串内容。与 name 参数的可选值一样,string 参数接受字符串、正则表达式、列表、True。

>>> soup.find_all('a', string='Elsie')
[<a class="sister" href="http://example.com/elsie" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="link1">Elsie</a>]

4.6 recursive 参数

调用 tag 的 find_all() 方法时,Beautiful Soup 会检索当前 tag 的所有子孙节点,如果只想搜索 tag 的直接子节点,可以使用参数 recursive=False。

4.6 find() 方法

它与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法只返回第一个匹配的结果。

4.7 get_text() 方法

如果只想得到 tag 中包含的文本内容,那么可以用 get_text() 方法,这个方法获取到 tag 中包含的所有文本内容。

>>> soup.find_all('a', string='Elsie')[0].get_text()
'Elsie'
>>> soup.find_all('a', string='Elsie')[0].string
'Elsie'

至此,Beautiful Soup 的常用使用方法已讲完,若果想了解更多内容,建议看下官方文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/。

总结

本篇主要带大家了解了 Beautiful Soup,结合一些小例子,相信大家对 Beautiful Soup 已不再陌生,下回会带大家结合 Beautiful Soup 进行爬虫的实战,欢迎继续关注!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中关于时间和日期函数的常用计算总结(time和datatime)
Mar 08 Python
python实现从一组颜色中找出与给定颜色最接近颜色的方法
Mar 19 Python
python制作花瓣网美女图片爬虫
Oct 28 Python
Python中死锁的形成示例及死锁情况的防止
Jun 14 Python
Python中使用asyncio 封装文件读写
Sep 11 Python
浅谈Python中的可变对象和不可变对象
Jul 07 Python
python中set()函数简介及实例解析
Jan 09 Python
PyTorch读取Cifar数据集并显示图片的实例讲解
Jul 27 Python
在 Jupyter 中重新导入特定的 Python 文件(场景分析)
Oct 27 Python
简单了解Pandas缺失值处理方法
Nov 16 Python
Django如何使用redis作为缓存
May 21 Python
浅析Python requests 模块
Oct 09 Python
Python实现模拟登录网易邮箱的方法示例
Jul 05 #Python
python selenium自动上传有赞单号的操作方法
Jul 05 #Python
python实现爬取图书封面
Jul 05 #Python
Python定义二叉树及4种遍历方法实例详解
Jul 05 #Python
Python使用pyodbc访问数据库操作方法详解
Jul 05 #Python
如何优雅地处理Django中的favicon.ico图标详解
Jul 05 #Python
解决pandas中读取中文名称的csv文件报错的问题
Jul 04 #Python
You might like
php中一个完整表单处理实现代码
2011/11/10 PHP
PHP遍历文件夹与文件类及处理类用法实例
2014/09/23 PHP
Jquery增加鼠标中间功能mousewheel的实例代码
2013/09/05 Javascript
JavaScript调用后台的三种方法实例
2013/10/17 Javascript
JavaScript代码生成PDF文件的方法
2016/02/26 Javascript
JavaScript随机生成颜色的方法
2016/10/15 Javascript
Zepto实现密码的隐藏/显示
2017/04/07 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
2017/06/19 Javascript
微信小程序内拖动图片实现移动、放大、旋转的方法
2018/09/04 Javascript
详解vue-cli+es6引入es5写的js(两种方法)
2019/04/19 Javascript
react结合bootstrap实现评论功能
2020/05/30 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
Python中的异常处理相关语句基础学习笔记
2016/07/11 Python
python查看微信好友是否删除自己
2016/12/19 Python
Python外星人入侵游戏编程完整版
2020/03/30 Python
python逆向入门教程
2018/01/15 Python
Pyecharts 动态地图 geo()和map()的安装与用法详解
2020/03/25 Python
JAVA及PYTHON质数计算代码对比解析
2020/06/10 Python
Python使用requests模块爬取百度翻译
2020/08/25 Python
python如何将图片转换素描画
2020/09/08 Python
linux centos 7.x 安装 python3.x 替换 python2.x的过程解析
2020/12/14 Python
html+js 实现markdown编辑器效果
2019/10/23 HTML / CSS
ProBikeKit英国:在线公路自行车之家
2017/02/10 全球购物
英国家用电器折扣网站:Electrical Discount UK
2018/09/17 全球购物
国际奢侈品品牌童装购物网站:Designer Childrenswear
2019/05/08 全球购物
Huda Beauty官方商店:化妆和美容产品
2020/09/05 全球购物
超市促销实习自我鉴定
2013/09/23 职场文书
法律专业应届本科毕业生求职信
2013/10/25 职场文书
市场营销专业推荐信
2013/11/03 职场文书
摄影展策划方案
2014/06/02 职场文书
寻找最美家庭活动方案
2014/08/20 职场文书
驳回起诉民事裁定书
2015/05/19 职场文书
红色革命电影观后感
2015/06/18 职场文书
谢师宴学生致辞
2015/07/27 职场文书
Java Dubbo框架知识点梳理
2021/06/26 Java/Android
java开发双人五子棋游戏
2022/05/06 Java/Android