CSS选择器:BeautifulSoup4

和lxml一样,Beautiful Soup也是一个HTML/XML的解析器,主要的功能也是如何解析和提取HTML/XML数据。

lxml只会局部遍历,而Beautiful Soup是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。

BeautifulSoup用来解析HTML比较简单,API非常人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持lxml的XML解析器。

Beautiful Soup3目前已经停止开发,推荐现在的项目使用Beautiful Soup。使用pip安装即可:pip install beautifulsoup4

官方文档: http://beautifulsoup.readthedocs.io/zh_CN/v4.4.0

抓取工具 速度 使用难道 安装难度
正则 最快 困难 无(内置)
BeautifulSoup 最简单 简单
lxml 简单 一般

实例:

首先必须要导入bs4库

  1. # 07-urllib2_beautipulsoup_prettify
  2. from bs4 import BeautifulSoup
  3. html = """
  4. <html><head><title>The Dormouse's story</title></head>
  5. <body>
  6. <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
  7. <p class="story">Once upon a time there were three little sisters; and their names were
  8. <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
  9. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  10. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  11. and they lived at the bottom of a well.</p>
  12. <p class="story">...</p>
  13. """
  14. #创建 Beautiful Soup 对象
  15. soup = BeautifulSoup(html)
  16. #打开本地 HTML 文件的方式来创建对象
  17. #soup = BeautifulSoup(open('index.html'))
  18. #格式化输出 soup 对象的内容
  19. print soup.prettify()

运行结果:

  1. <html>
  2. <head>
  3. <title>
  4. The Dormouse's story
  5. </title>
  6. </head>
  7. <body>
  8. <p class="title" name="dromouse">
  9. <b>
  10. The Dormouse's story
  11. </b>
  12. </p>
  13. <p class="story">
  14. Once upon a time there were three little sisters; and their names were
  15. <a class="sister" href="http://example.com/elsie" id="link1">
  16. <!-- Elsie -->
  17. </a>
  18. ,
  19. <a class="sister" href="http://example.com/lacie" id="link2">
  20. Lacie
  21. </a>
  22. and
  23. <a class="sister" href="http://example.com/tillie" id="link3">
  24. Tillie
  25. </a>
  26. ;
  27. and they lived at the bottom of a well.
  28. </p>
  29. <p class="story">
  30. ...
  31. </p>
  32. </body>
  33. </html>
  • 如果我们在IPython2下执行,会看到这样一段警告:

  • 意思是,如果我们没有显示地指定解析器,所以默认使用这个系统的最佳可用HTML解析器("lxml")。如果你在另一个系统中运行这段代码,或者在不同的虚拟环境中,使用不同的解析器造成行为不同。
  • 但是我们可以通过soup = BeautifulSoup(html, "lxml")

四大对象种类

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

  • Tag
  • NaviganleString
  • BeautifulSoup
  • Comment

1.Tag

Tag通俗点讲就是HTM中的一个个标签,例如:

  1. <head><title>The Dormouse's story</title></head>
  2. <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
  3. <p class="title" name="dromouse"><b>The Dormouse's story</b></p>

上面的titleheadap等等标签上加上里面包括的内容就是Tag,那么试着使用Beautiful Soup来获取Tags

  1. #-*- coding:utf-8 -*-
  2. #08-urllib2_beautifulsoup_tag.py
  3. from bs4 import BeautifulSoup
  4. html = """
  5. <html><head><title>The Dormouse's story</title></head>
  6. <body>
  7. <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
  8. <p class="story">Once upon a time there were three little sisters; and their names were
  9. <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
  10. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  11. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  12. and they lived at the bottom of a well.</p>
  13. <p class="story">...</p>
  14. """
  15. #创建Beautiful Soup对象
  16. soup = BeautifulSoup(html)
  17. print soup.title
  18. #<title>The Dormouse's story</title>
  19. print soup.a
  20. #<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
  21. print soup.p
  22. #<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
  23. print type(soup.p)
  24. # <class 'bs4.element.Tag'>

我们可以利用 soup 加标签名轻松地获取这些标签的内容,这些对象的类型是bs4.element.Tag。但是注意,它查找的是在所有内容中的第一个符合要求的标签。如果要查询所有的标签,后面会进行介绍。

对于Tag,它有两个重要的属性,是name和attrs

  1. print soup.name
  2. #[document] #soup对象本身比较特殊,它的name即为[document]
  3. print soup.head.name
  4. #head #对于其他内部标签,输出的值便为标签本身的名称
  5. print soup.p.attrs
  6. #{'class':['title'], 'name':'dromouse'}
  7. #在这里,我们把p标签的所有属性打印出来,得到的类型是一个字典
  8. print soup.p['class'] #soup.p.get('class')
  9. #['title'] #还可以利用get方法,传入属性的方法,二者是等价的。
  10. soup.a['class'] = 'newClass'
  11. print soup.p #可以对这些属性和内容等等进行修改
  12. # <p class="newClass" name="dromouse"><b>The Dormouse's story</b></p>
  13. del soup.p['class'] #还可以对这个属性进行删除
  14. print soup.p
  15. # <p name="dromouse"><b>The Dormouse's story</b></p>

2. NavigableString

既然我们已经得到了标签的内容,那么问题来了,我们要想获取标签内部的文字怎么办呢?很简单,用.string即可,例如

  1. print soup.p.string
  2. #The Dormouse's story
  3. print type(soup.p.string)
  4. <class 'bs4.element.NavigableString'>

3. BeautifulSoup

BeautifulSoup对象表示的是一个文档的内容。大部门时候,可以用它当做Tag对象,是一个特殊的Tag,我们可以分别获取它的类型,名称,以及属性来感受一下。

  1. print type(soup.name)
  2. #<type 'unicode'>
  3. print soup.name
  4. #[document]
  5. print soup.attrs #文档本身的属性为空
  6. #{}

4. Comment

Comment对象时一个特殊类型的NavigableString对象,其输出的内容不包括注释符号。

  1. print soup.a
  2. # <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
  3. print soup.a.string
  4. #Elsie
  5. print type(soup.a.string)
  6. # <class 'bs4.element.Comment'>

a标签里的内容实际上是注释,但是如果我们利用.string来输出它的内容时,注释符号已经去掉了。

遍历文档树

1.直接子节点:.contents .children属性

.content

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

  1. print soup.head.contents
  2. #[<title>The Dormouse's story</title>]

输出方式为列表,我们可以用列表索引来获取它的某一个元素

  1. print soup.head.contents[0]
  2. #<title>The Dormouse's story</title>

.children

它返回的不是一个list,不过我们可以通过遍历获取所有子节点。

我们打印输出.children看一下,可以发现他是一个list生成器对象。

  1. print soup.head.children
  2. #<listiterator object at 0x7f71457f5710>
  3. for child in soup.body.children:
  4. print child

结果:

  1. <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
  2. <p class="story">Once upon a time there were three little sisters; and their names were
  3. <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
  4. <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
  5. <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
  6. and they lived at the bottom of a well.</p>
  7. <p class="story">...</p>

2. 所有子孙节点:.descendants属性

.contents和.children属性仅包含tag的直接子节点,.descendants属性可以对所有tag的子孙节点进行递归循环,和.children类似,我们也需要遍历获取其中的内容。

  1. for child in soup.descendants:
  2. print child

3. 节点内容:.string属性

如果tag只有一个NavigableString类型子节点,那么这个tag可以使用.string得到子节点。如果一个tag仅有一个子节点,那么这个tag也可以使用.string,输出结果与当前唯一子节点的.string结果相同。

通俗点讲就是:如果一个标签里面没有标签了,那么.string就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么.string也会返回最里面的内容。例如:

  1. print soup.head.string
  2. #The Dormouse's story
  3. print soup.title.string
  4. #The Dormouse's story

搜索文档树

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

1) name参数

name参数可以查找所有民资为name的tag,字符串对象会自动忽略掉。

A.传字符串

最简单的过滤器是字符串,在搜索方法中传入一个字符串参数,eautiful Soup会自动查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的标签:

  1. soup.find_all('b')
  2. #[<b>The Dormouse's story</b>]
  3. print soup.find_all('a')
  4. #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

B.传正则表达式

如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的match()来匹配内容。下面例子中找出所有以b开头的标签,这表示<body><b>标签都应该被找到。

  1. import re
  2. for tag in soup.find_all(re.compile('^b')):
  3. print(tag.name)
  4. #body
  5. #b

C.传列表

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回 下面代码找到文档中所有<a>标签和<b>标签:

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

2) keyword参数

  1. soup.find_all(id='link2')
  2. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

3) text参数

通过text参数可以搜索文档中的字符串内容,与name参数的可选值一样,text参数接收参数值,正则表达式,列表

  1. soup.find_all(text='Elsie')
  2. #[u'Elsie']
  3. soup.find_all(text=['Tillie', 'Elsie', 'Lacie'])
  4. # [u'Elsie', u'Lacie', u'Tillie']
  5. soup.find_all(text=re.compile("Dormouse"))
  6. [u"The Dormouse's story", u"The Dormouse's story"]

CSS选择器

这就是另一种与 find_all 方法有异曲同工之妙的查找方法.

  • 写 CSS 时,标签名不加任何修饰,类名前加.,id名前加#
  • 在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list

Python爬虫(十四)_BeautifulSoup4 解析器的更多相关文章

  1. Python 爬虫十六式 - 第五式:BeautifulSoup-美味的汤

    BeautifulSoup 美味的汤 学习一时爽,一直学习一直爽!    Hello,大家好,我是Connor,一个从无到有的技术小白.上一次我们说到了 Xpath 的使用方法.Xpath 我觉得还是 ...

  2. python爬虫的页面数据解析和提取/xpath/bs4/jsonpath/正则(1)

    一.数据类型及解析方式 一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值.内容一般分为两部分,非结构化的数据 和 结构化的数据. 非结构化数据:先有数据,再有结构, 结构化数 ...

  3. Python 爬虫十六式 - 第七式:正则的艺术

    RE:用匹配来演绎编程的艺术 学习一时爽,一直学习一直爽   Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 pyquery 今天我们将迎来我们数据匹配部分的最后一位 ...

  4. Python 爬虫十六式 - 第二式:urllib 与 urllib3

    Python请求标准库 urllib 与 urllib3 学习一时爽,一直学习一直爽!   大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了什么是HTTP协议,那么这一次我们就要动 ...

  5. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

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

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

  7. Python爬虫进阶四之PySpider的用法

    审时度势 PySpider 是一个我个人认为非常方便并且功能强大的爬虫框架,支持多线程爬取.JS动态解析,提供了可操作界面.出错重试.定时爬取等等的功能,使用非常人性化. 本篇内容通过跟我做一个好玩的 ...

  8. Python爬虫入门四之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  9. Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery

    PyQuery:一个类似jquery的python库 学习一时爽,一直学习一直爽   Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 BeautifulSoup 美味 ...

随机推荐

  1. jquerymobile实例介绍

    [创建页面]   data-role="page" 是在浏览器中显示的页面..   data-theme="b"更换主题,有a和b两种   data-role= ...

  2. 【20171106早】BeEF 工具初探

    老黑今天接触BeEF工具,首先要了解这个工具能够做什么? 0x01:功能介绍 专业文档:点击这里 通俗的说就是可以控制别的浏览器,获取浏览器的信息.然后做something 专业的说就是好用的渗透测试 ...

  3. number 类型转换 符号

    function convert(sValue, sDataType) {   switch(sDataType) {      case “int”:          return parseIn ...

  4. jQuery选择器(ID选择器)第一节

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  5. 64位win7下安装Boost 1.59.0 + boost.python 1.59.0 + gccxml + pygccxml + pyplusplus(py++)

    由于安装过程中实在是出现了N多问题,所以不得不专门写个帖子来记录一下这破东西在Win7下的安装过程,避免以后还要再用的时候踩坑. 1.Boost简介 Boost库是一个可移植.提供源代码的C++库,作 ...

  6. C#只能运行一个实例程序的方法

    互斥进程(程序), 简单点说,就是在系统中只能有该程序的一个实例运行. 现在很多软件都有这功能,如Maxthon 可以设置为"只允许打开一个窗体",还有Bitcomet等. 我也是 ...

  7. C#动态获取鼠标坐标

    .Net封装好的方法 int Control.MousePosition.X;int Control.MousePosition.Y; 用API方法 using System.Runtime.Inte ...

  8. Redis轻快入门

    Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMware主 ...

  9. 前端面试题(6)图片格式jpg,gif,png-8,png-24的区别,及其各自的使用场景

    Gif格式特点: 透明性,Gif是一种布尔透明类型,既它可以是全透明,也可以是全不透明,但是它并没有半透明(alpha透明). 动画,Gif这种格式支持动画. 无损耗性,Gif是一种无损耗的图像格式, ...

  10. tornado之Hello world

    #!/usr/bin/env python26 #-*- coding:utf8 -*- import tornado.httpserver import tornado.ioloop import ...