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之眼花缭乱的运算符
Sep 14 Python
Python字符串中查找子串小技巧
Apr 10 Python
python使用分治法实现求解最大值的方法
May 12 Python
Python的Flask框架中配置多个子域名的方法讲解
Jun 07 Python
浅述python中深浅拷贝原理
Sep 18 Python
在python中只选取列表中某一纵列的方法
Nov 28 Python
python用for循环求和的方法总结
Jul 08 Python
浅析NumPy 切片和索引
Sep 02 Python
python 实现&quot;神经衰弱&quot;翻牌游戏
Nov 09 Python
Python识别处理照片中的条形码
Nov 16 Python
安装python依赖包psycopg2来调用postgresql的操作
Jan 01 Python
Python爬虫之爬取某文库文档数据
Apr 21 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
便携利器 — TECSUN PL-365简评
2021/03/02 无线电
很温暖很温暖的Lester Young
2021/03/03 冲泡冲煮
PHP中register_globals参数为OFF和ON的区别(register_globals 使用详解)
2012/02/05 PHP
PHP版QQ互联OAuth示例代码分享
2015/07/05 PHP
php组合排序简单实现方法
2016/10/15 PHP
浅谈php中curl、fsockopen的应用
2016/12/10 PHP
php基于Redis消息队列实现的消息推送的方法
2018/11/28 PHP
PHP addslashes()函数讲解
2019/02/03 PHP
Laravel框架路由管理简单示例
2019/05/07 PHP
jquery 读取页面load get post ajax 四种方式代码写法
2011/04/02 Javascript
javascript权威指南 学习笔记之变量作用域分享
2011/09/28 Javascript
JS完成代码前最好对其做5件事
2013/04/07 Javascript
解读JavaScript中 For, While与递归的用法
2013/05/07 Javascript
jquery学习总结(超级详细)
2014/09/04 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
2015/04/15 Javascript
使用AngularJS对路由进行安全性处理的方法
2015/06/18 Javascript
Vue.js实现微信过渡动画左右切换效果
2017/06/13 Javascript
React如何利用相对于根目录进行引用组件详解
2017/10/09 Javascript
python中的__init__ 、__new__、__call__小结
2014/04/25 Python
Python中对象迭代与反迭代的技巧总结
2016/09/17 Python
Python爬虫_城市公交、地铁站点和线路数据采集实例
2018/01/10 Python
python基于socket模拟实现ssh远程执行命令
2020/12/05 Python
CSS3按钮鼠标悬浮实现光圈效果源码
2016/09/11 HTML / CSS
突袭HTML5之Javascript API扩展1—Web Worker异步执行及相关概述
2013/01/31 HTML / CSS
KEETSA环保床垫:更好的睡眠,更好的生活!
2016/11/24 全球购物
海信商城:海信电视、科龙空调、容声冰箱官方专卖
2017/02/07 全球购物
日本最大的旅游网站:Rakuten Travel(乐天旅游)
2018/08/02 全球购物
Nisbets法国:英国最大的厨房和餐饮设备供应商
2019/03/18 全球购物
GWT (Google Web Toolkit)有哪些主要的原件组成?
2015/06/08 面试题
教育专业毕业生推荐信
2014/07/10 职场文书
副乡长民主生活会个人对照检查材料思想汇报
2014/10/01 职场文书
公司委托书格式范文
2014/10/09 职场文书
2014年安全生产工作总结
2014/11/13 职场文书
2014年行政工作总结
2014/11/19 职场文书
社交电商模式的兴起:这些新的商机千万别错过
2019/07/26 职场文书
php实例化对象的实例方法
2021/11/17 PHP