Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库,简单来说,它能将HTML的标签文件解析成树形结构,然后方便地获取到指定标签的对应属性。

如在上一篇文章通过爬虫爬取漫画图片,获取信息纯粹用正则表达式进行处理,这种方式即复杂,代码的可阅读性也低。通过Beautiful Soup库,我们可以将指定的class或id值作为参数,来直接获取到对应标签的相关数据,这样的处理方式简洁明了。

当前最新的 Beautiful Soup 版本为4.4.0,Beautiful Soup 3 当前已停止维护。

Beautiful Soup 4 可用于 Python2.7 和 Python3.0,本文示例使用的Python版本为2.7。

博主使用的是Mac系统,直接通过命令安装库:

  1. sudo easy_install beautifulsoup4

安装完成后,尝试包含库运行:

  1. from bs4 import BeautifulSoup

若没有报错,则说明库已正常安装完成。

开始

本文会通过这个网页http://reeoo.com来进行示例讲解,如下图所示

1.jpg

BeautifulSoup 对象初始化

将一段文档传入 BeautifulSoup 的构造方法,就能得到一个文档对象。如下代码所示,文档通过请求url获取:

  1. #coding:utf-8
  2. from bs4 import BeautifulSoup
  3. import urllib2
  4. url = 'http://reeoo.com'
  5. request = urllib2.Request(url)
  6. response = urllib2.urlopen(request, timeout=20)
  7. content = response.read()
  8. soup = BeautifulSoup(content, 'html.parser')

request 请求没有做异常处理,这里暂时先忽略。BeautifulSoup 构造方法的第二个参数为文档解析器,若不传入该参数,BeautifulSoup会自行选择最合适的解析器来解析文档,不过会有警告提示。

也可以通过文件句柄来初始化,可先将HTML的源码保存到本地同级目录 reo.html,然后将文件名作为参数:

  1. soup = BeautifulSoup(open('reo.html'))

可以打印 soup,输出内容和HTML文本无二致,此时它为一个复杂的树形结构,每个节点都是Python对象。

Ps. 接下来示例代码中所用到的 soup 都为该soup。

Tag

Tag对象与HTML原生文档中的标签相同,可以直接通过对应名字获取

  1. tag = soup.title
  2. print tag

打印结果:

  1. <title>Reeoo - web design inspiration and website gallery</title>

Name

通过Tag对象的name属性,可以获取到标签的名称

  1. print tag.name
  2. # title

Attributes

一个tag可能包含很多属性,如id、class等,操作tag属性的方式与字典相同。

例如网页中包含缩略图区域的标签 article

  1. ...
  2. <article class="box">
  3. <div id="main">
  4. <ul id="list">
  5. <li id="sponsor"><div class="sponsor_tips"></div>
  6. <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1696&serve=CVYD42T&placement=reeoocom" id="_carbonads_js"></script>
  7. </li>
  8. ...

获取它 class 属性的值

  1. tag = soup.article
  2. c = tag['class']
  3. print c
  4. # [u'box']

也可以直接通过 .attrs 获取所有的属性

  1. tag = soup.article
  2. attrs = tag.attrs
  3. print attrs
  4. # {u'class': [u'box']}

ps. 因为class属于多值属性,所以它的值为数组。

tag中的字符串

通过 string 方法获取标签中包含的字符串

  1. tag = soup.title
  2. s = tag.string
  3. print s
  4. # Reeoo - web design inspiration and website gallery

文档树的遍历

一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点。Beautiful Soup提供了许多操作和遍历子节点的属性。

子节点

通过Tagname 可以获取到对应标签,多次调用这个方法,可以获取到子节点中对应的标签。

如下图:

2.jpg

我们希望获取到 article 标签中的 li

  1. tag = soup.article.div.ul.li
  2. print tag

打印结果:

  1. <li id="sponsor"><div class="sponsor_tips"></div>
  2. <script async="" id="_carbonads_js" src="//cdn.carbonads.com/carbon.js?zoneid=1696&serve=CVYD42T&placement=reeoocom" type="text/javascript"></script>
  3. </li>

也可以把中间的一些节点省略,结果也一致

  1. tag = soup.article.li

通过 . 属性只能获取到第一个tag,若想获取到所有的 li 标签,可以通过 find_all() 方法

  1. ls = soup.article.div.ul.find_all('li')

获取到的是包含所有li标签的列表。

tag的 .contents 属性可以将tag的子节点以列表的方式输出:

  1. tag = soup.article.div.ul
  2. contents = tag.contents

打印 contents 可以看到列表中不仅包含了 li 标签内容,还包括了换行符 '\n'

过tag的 .children 生成器,可以对tag的子节点进行循环

  1. tag = soup.article.div.ul
  2. children = tag.children
  3. print children
  4. for child in children:
  5. print child

可以看到 children 的类型为 <listiterator object at 0x109cb1850>

.contents.children 属性仅包含tag的直接子节点,若要遍历子节点的子节点,可以通过 .descendants 属性,方法与前两者类似,这里不列出来了。

父节点

通过 .parent 属性来获取某个元素的父节点,article 的 父节点为 body。

  1. tag = soup.article
  2. print tag.parent.name
  3. # body

或者通过 .parents 属性遍历所有的父辈节点。

  1. tag = soup.article
  2. for p in tag.parents:
  3. print p.name

兄弟节点

.next_sibling.previous_sibling 属性用来插叙兄弟节点,使用方式与其他的节点类似。

文档树的搜索

对树形结构的文档进行特定的搜索是爬虫抓取过程中最常用的操作。

find_all()

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

name 参数

查找所有名字为 name 的tag

  1. soup.find_all('title')
  2. # [<title>Reeoo - web design inspiration and website gallery</title>]
  3. soup.find_all('footer')
  4. # [<footer id="footer">\n<div class="box">\n<p> ... </div>\n</footer>]
keyword 参数

如果指定参数的名字不是内置的参数名(name , attrs , recursive , string),则将该参数当成tag的属性进行搜索,不指定tag的话则默认为对所有tag进行搜索。

如,搜索所有 id 值为 footer 的标签

  1. soup.find_all(id='footer')
  2. # [<footer id="footer">\n<div class="box">\n<p> ... </div>\n</footer>]

加上标签的参数

  1. soup.find_all('footer', id='footer')
  2. # [<footer id="footer">\n<div class="box">\n<p> ... </div>\n</footer>]
  3. # 没有id值为'footer'的div标签,所以结果返回为空
  4. soup.find_all('div', id='footer')
  5. # []

获取所有缩略图的 div 标签,缩略图用 classthumb 标记

  1. soup.find_all('div', class_='thumb')

这里需要注意一点,因为 class 为Python的保留关键字,所以作为参数时加上了下划线,为“class_”。

指定名字的属性参数值可以包括:字符串正则表达式列表True/False

True/False

是否存在指定的属性。

搜索所有带有 target 属性的标签

  1. soup.find_all(target=True)

搜索所有不带 target 属性的标签(仔细观察会发现,搜索结果还是会有带 target 的标签,那是不带 target 标签的子标签,这里需要注意一下。)

  1. soup.find_all(target=False)

可以指定多个参数作为过滤条件,例如页面缩略图部分的标签如下所示:

  1. ...
  2. <li>
  3. <div class="thumb">
  4. <a href="http://reeoo.com/aim-creative-studios">![AIM Creative Studios](//upload-images.jianshu.io/upload_images/1346917-f6281ffe1a8f0b18.gif?imageMogr2/auto-orient/strip)</a>
  5. </div>
  6. <div class="title">
  7. <a href="http://reeoo.com/aim-creative-studios">AIM Creative Studios</a>
  8. </div>
  9. </li>
  10. ...

搜索 src 属性中包含 reeoo 字符串,并且 classlazy 的标签:

  1. soup.find_all(src=re.compile("reeoo.com"), class_='lazy')

搜索结果即为所有的缩略图 img 标签。

有些属性不能作为参数使用,如 data-* 属性。在上面的例子中,data-original 不能作为参数使用,运行起来会报错,SyntaxError: keyword can't be an expression

attrs 参数

定义一个字典参数来搜索对应属性的tag,一定程度上能解决上面提到的不能将某些属性作为参数的问题。

例如,搜索包含 data-original 属性的标签

  1. print soup.find_all(attrs={'data-original': True})

搜索 data-original 属性中包含 reeoo.com 字符串的标签

  1. soup.find_all(attrs={'data-original': re.compile("reeoo.com")})

搜索 data-original 属性为指定值的标签

  1. soup.find_all(attrs={'data-original': 'http://media.reeoo.com/Bersi Serlini Franciacorta.png!page'})
string 参数

name 参数类似,针对文档中的字符串内容。

搜索包含 Reeoo 字符串的标签:

  1. soup.find_all(string=re.compile("Reeoo"))

打印搜索结果可看到包含3个元素,分别是对应标签里的内容,具体见下图所示

3.jpg

4.jpg

5.jpg
limit 参数

find_all() 返回的是整个文档的搜索结果,如果文档内容较多则搜索过程耗时过长,加上 limit 限制,当结果到达 limit 值时停止搜索并返回结果。

搜索 classthumbdiv 标签,只搜索3个

  1. soup.find_all('div', class_='thumb', limit=3)

打印结果为一个包含3个元素的列表,实际满足结果的标签在文档里不止3个。

recursive 参数

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

find()

find(name , attrs , recursive , string , * kwargs)*

find() 方法和 find_all() 方法的参数使用基本一致,只是 find() 的搜索方法只会返回第一个满足要求的结果,等价于 find_all() 方法并将limit设置为1。

  1. soup.find_all('div', class_='thumb', limit=1)
  2. soup.find('div', class_='thumb')

搜索结果一致,唯一的区别是 find_all() 返回的是一个数组,find() 返回的是一个元素。

当没有搜索到满足条件的标签时,find() 返回 None, 而 find_all() 返回一个空的列表。

CSS选择器

TagBeautifulSoup 对象通过 select() 方法中传入字符串参数, 即可使用CSS选择器的语法找到tag。

语义和CSS一致,搜索 article 标签下的 ul 标签中的 li 标签

  1. print soup.select('article ul li')

通过类名查找,两行代码的结果一致,搜索 classthumb 的标签

  1. soup.select('.thumb')
  2. soup.select('[class~=thumb]')

通过id查找,搜索 idsponsor 的标签

  1. soup.select('#sponsor')

通过是否存在某个属性来查找,搜索具有 id 属性的 li 标签

  1. soup.select('li[id]')

通过属性的值来查找查找,搜索 idsponsorli 标签

  1. soup.select('li[id="sponsor"]')

其他

其他的搜索方法还有:

find_parents()find_parent()

find_next_siblings()find_next_sibling()

find_previous_siblings()find_previous_sibling()

...

参数的作用和 find_all()find() 差别不大,这里就不再列举使用方式了。这两个方法基本已经能满足绝大部分的查询需求。

还有一些方法涉及文档树的修改。对于爬虫来说大部分工作只是检索页面的信息,很少需要对页面源码做改动,所以这部分的内容也不再列举。

具体详细信息可直接参考Beautiful Soup库的官方说明文档

【完】。 :)

原网址:http://www.jianshu.com/p/5c239bcd05a3

Python爬虫库-Beautiful Soup的使用的更多相关文章

  1. Python爬虫之Beautiful Soup解析库的使用(五)

    Python爬虫之Beautiful Soup解析库的使用 Beautiful Soup-介绍 Python第三方库,用于从HTML或XML中提取数据官方:http://www.crummv.com/ ...

  2. python 爬虫利器 Beautiful Soup

    python 爬虫利器 Beautiful Soup Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文 ...

  3. [Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息

    [Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息 2018-07-21 23:53:02 larger5 阅读数 4123更多 分类专栏: 网络爬虫   版权声明: ...

  4. python爬虫之Beautiful Soup基础知识+实例

    python爬虫之Beautiful Soup基础知识 Beautiful Soup是一个可以从HTML或XML文件中提取数据的python库.它能通过你喜欢的转换器实现惯用的文档导航,查找,修改文档 ...

  5. python爬虫之Beautiful Soup的基本使用

    1.简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索 ...

  6. python标准库Beautiful Soup与MongoDb爬喜马拉雅电台的总结

    Beautiful Soup标准库是一个可以从HTML/XML文件中提取数据的Python库,它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式,Beautiful Soup将会节省数小 ...

  7. python 爬虫5 Beautiful Soup的用法

    1.创建 Beautiful Soup 对象 from bs4 import BeautifulSoup html = """ <html><head& ...

  8. Python爬虫之Beautiful Soup库的基本使用

  9. 小白学 Python 爬虫(21):解析库 Beautiful Soup(上)

    小白学 Python 爬虫(21):解析库 Beautiful Soup(上) 人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前 ...

随机推荐

  1. easyui combotree选项重复

    现象 编辑,赋值出现重复选项 原因 值之间有空格,比如我取值是3, 4, 6要改成3,4,6 注意:数值之间的空格去掉了

  2. 如何删除Windows 7的保留分区

    Windows 7的保留分区可以删除,但是必须小心.启动到Windows 7,运行具有管理员权限的CMD.exe,然后输入:diskpartsel disk 0list volsel vol 0 (你 ...

  3. [Analytics] Add Tealium debugger in Chrome

    It would be helpful once you can see what information have been tracking inside you web application, ...

  4. Office WORD如何输入长下划线

    选中一段文字,点击下划线按钮,可以添加下划线   同样,选中一段空格,点下划线,也可以添加下划线    

  5. Material UI:很强大的CSS框架

    Material UI 是一款功能很强大,界面却十分清新简洁的CSS框架.Material UI利用了Google的Material Design 全新设计语言.而且让每个UI组件都变得很独立.因此开 ...

  6. Codeforces Round #221 (Div. 2) D

    有点郁闷的题目,给了2000ms,可是n,m的范围已经是5000了.5000 * 5000一般在别的OJ已经是超了2000ms,一開始不敢敲.看了下别人有n*m的潜逃循环,原来CF的机子如此的强大,一 ...

  7. 数据结构与算法问题 AVL二叉平衡树

    AVL树是带有平衡条件的二叉查找树. 这个平衡条件必须保持,并且它必须保证树的深度是O(logN). 一棵AVL树是其每一个节点的左子树和右子树的高度最多差1的二叉查找树. (空树的高度定义为-1). ...

  8. C语言细节笔记1

    /******************************************************************************* ——笔记 1. 函数申明的书写. 可以 ...

  9. 自定义实现JavaScript的Map对象,修改IE不兼容MAP()的问题

    由于IE8及以下版本不支持Map对象,本文为程序猿们提供了有效的解决方法. 本文重写了Map对象,实现了常用的set, get, put, clear, remove, delete, forEach ...

  10. 2016/05/25 empty() 与 isset()的区别

    对于初学php的人来说,empty()和和isset()用法的区别是很难搞清楚的,他们的用法的差别不仔细去琢磨的话确实很难弄清楚. 先说一下他们的共同点: 都可以判定一个变量是否为空: 都返回bool ...