08. 数据提取-Beautiful Soup

08. 数据提取-Beautiful Soup

一月 08, 2020

1. Beautiful Soup的简介

Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。

Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。

Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度

官网http://beautifulsoup.readthedocs.io/zh_CN/latest/

2. Beautiful Soup 安装

Beautiful Soup 3 目前已经停止开发,推荐在现在的项目中使用Beautiful Soup 4,不过它已经被移植到BS4了,也就是说导入时我们需要 import bs4

1
pip install beautifulsoup4

Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装

解析器 使用方法 优势 劣势
Python标准库 BeautifulSoup(markup, “html.parser”) 1. Python的内置标准库 2. 执行速度适中 3.文档容错能力强 Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
lxml HTML 解析器 BeautifulSoup(markup, “lxml”) 1. 速度快 2.文档容错能力强 需要安装C语言库
lxml XML 解析器 BeautifulSoup(markup, [“lxml”, “xml”]) BeautifulSoup(markup, “xml”) 1. 速度快 2.唯一支持XML的解析器 3.需要安装C语言库
html5lib BeautifulSoup(markup, “html5lib”) 1. 最好的容错性 2.以浏览器的方式解析文档 3.生成HTML5格式的文档 4.速度慢 不依赖外部扩展

3. 创建 Beautiful Soup 对象

1
2
3
from bs4 import BeautifulSoup

bs = BeautifulSoup(html,"lxml")

4. 四大对象种类

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

  • Tag
  • NavigableString
  • BeautifulSoup
  • Comment

4.1 Tag 是什么?通俗点讲就是 HTML 中的一个个标签

例如:<div> <title>

使用方式:

1
2
3
4
5
6
7
8
#以以下代码为例子
<title>尚学堂</title>
<div class='info' float='left'>Welcome to SXT</div>
<div class='info' float='right'>
<span>Good Good Study</span>
<a href='www.bjsxt.cn'></a>
<strong><!--没用--></strong>
</div>
4.1.1 获取标签
1
2
3
4
#以lxml方式解析
soup = BeautifulSoup(info, 'lxml')
print(soup.title)
# <title>尚学堂</title>

注意

相同的标签只能获取第一个符合要求的标签

4.1.2 获取属性:
1
2
3
4
5
6
7
8
9
#获取所有属性
print(soup.title.attrs)
#class='info' float='left'

#获取单个属性的值
print(soup.div.get('class'))
print(soup.div['class'])
print(soup.a['href'])
#info

4.2 NavigableString 获取内容

1
2
3
print(soup.title.string)
print(soup.title.text)
#尚学堂

4.3 BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.

因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name

1
2
3
4
print(soup.name)
print(soup.head.name)
# [document]
# head

4.4 Comment

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

1
2
3
4
if type(soup.strong.string)==Comment:
print(soup.strong.prettify())
else:
print(soup.strong.string)

5 搜索文档树

Beautiful Soup定义了很多搜索方法,这里着重介绍2个: find() 和 find_all() .其它方法的参数和用法类似,请同学们举一反三

5.1 过滤器

介绍 find_all() 方法前,先介绍一下过滤器的类型 ,这些过滤器贯穿整个搜索的API.过滤器可以被用在tag的name中,节点的属性中,字符串中或他们的混合中

5.1.1 字符串

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

标签

1
2
#返回所有的div标签
print(soup.find_all('div'))

如果传入字节码参数,Beautiful Soup会当作UTF-8编码,可以传入一段Unicode 编码来避免Beautiful Soup解析编码出错

5.1.2 正则表达式

如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容

1
2
#返回所有的div标签
print (soup.find_all(re.compile("^div")))
5.1.3 列表

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回

1
2
#返回所有匹配到的span a标签
print(soup.find_all(['span','a']))
5.1.4 keyword

如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性

1
2
#返回id为welcom的标签
print(soup.find_all(id='welcom'))
5.1.4 True

True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点

5.1.5 按CSS搜索

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

1
2
# 返回class等于info的div
print(soup.find_all('div',class_='info'))

5.1.6 按属性的搜索

1
soup.find_all("div", attrs={"class": "info"})

6. CSS选择器(扩展)

soup.select(参数)

表达式 说明
tag 选择指定标签
* 选择所有节点
#id 选择id为container的节点
.class 选取所有class包含container的节点
li a 选取所有li下的所有a节点
ul + p (兄弟)选择ul后面的第一个p元素
div#id > ul (父子)选取id为id的div的第一个ul子元素
table ~ div 选取与table相邻的所有div元素
a[title] 选取所有有title属性的a元素
a[class=”title”] 选取所有class属性为title值的a
a[href*=”sxt”] 选取所有href属性包含sxt的a元素
a[href^=”http”] 选取所有href属性值以http开头的a元素
a[href$=”.png”] 选取所有href属性值以.png结尾的a元素
input[type=”redio”]:checked 选取选中的hobby的元素