BS4

摘要:
BeautifulSoup库通常称为bs4库,支持Python 3。对于我们来说,这是一个非常好的第三方库来编写爬虫。通过PyPi安装BeautifulSoupBeautiful Soup4,因此如果您无法使用系统包来管理安装,您也可以使用easy_Install或pip$easy_Installbeautifuloup4$pipinstallbeautifuuloup4。如果您没有安装easy_Install和pip,您还可以下载BS4的源代码并通过安装程序进行安装,它支持Python标准库中的HTML解析器,以及一些第三方解析器,其中一个是lxml。

Beautiful Soup 库一般被称为bs4库,支持Python3,是我们写爬虫非常好的第三方库。因用起来十分的简便流畅。所以也被人叫做“美味汤”。下文会介绍该库的最基本的使用。

安装 Beautiful Soup

Beautiful Soup 4 通过PyPi发布,所以如果你无法使用系统包管理安装,那么也可以通过easy_install 或 pip 来安装。包的名字是 beautifulsoup4 ,这个包兼容Python2和Python3。

easy_install beautifulsoup4

pip install beautifulsoup4

如果你没有安装 easy_install 或 pip ,那你也可以 下载BS4的源码 ,然后通过setup.py来安装。

Python setup.py install

安装解析器

Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是lxml。根据操作系统不同,可以选择下列方法来安装lxml:

apt-get install Python-lxml

easy_install lxml

pip install lxml

另一个可供选择的解析器是纯Python实现的html5lib, html5lib的解析方式与浏览器相同,可以选择下列方法来安装html5lib:

apt-get install Python-html5lib

easy_install html5lib

pip install html5lib

下表列出了主要的解析器,以及它们的优缺点:

解析器使用方法优势劣势
Python标准库BeautifulSoup(markup,"html.parser")
  • Python的内置标准库
  • 执行速度适中
  • 文档容错能力强
  • Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
lxml HTML 解析器BeautifulSoup(markup,"lxml")
  • 速度快
  • 文档容错能力强
  • 需要安装C语言库
lxml XML 解析器

BeautifulSoup(markup,["lxml-xml"])

BeautifulSoup(markup,"xml")

  • 速度快
  • 唯一支持XML的解析器
  • 需要安装C语言库
html5libBeautifulSoup(markup,"html5lib")
  • 最好的容错性
  • 以浏览器的方式解析文档
  • 生成HTML5格式的文档
  • 速度慢
  • 不依赖外部扩展

推荐使用lxml作为解析器,因为效率更高。在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib,因为那些Python版本的标准库中内置的HTML解析方法不够稳定。

提示:如果一段HTML或XML文档格式不正确的话,那么在不同的解析器中返回的结果可能是不一样的,查看 解析器之间的区别 了解更多细节。

这里我们先简单的讲解一下bs4库的使用,暂时不去考虑如何从web上抓取网页,假设我们需要爬去的html是如下这么一段:

html
<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
http://example.com/elsie" class="sister" id="link1">Elsie,
http://example.com/lacie" class="sister" id="link2">Lacie and
http://example.com/tillie" class="sister" id="link3">Tillie;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
</html>
1 #导入bs4模块
2 from bs4 import BeautifulSoup
3 soup = BeautifulSoup(html,'html.parser')
4 #输出结果
5 print(soup.prettify())

结果:

`html
<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
http://example.com/elsie" class="sister" id="link1"&gt;Elsie,
http://example.com/lacie" class="sister" id="link2"&gt;Lacie and
http://example.com/tillie" class="sister" id="link3"&gt;Tillie;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>

可以看到bs4库将网页文件变成了一个soup的类型,事实上,bs4库 是解析、遍历、维护、“标签树“的功能库。

通俗一点说就是: bs4库把html源代码重新进行了格式化,从而方便我们对其中的节点、标签、属性等进行操作。

 1 #找到文档的title
 2 print(soup.title)
 3 # <title>The Dormouse's story</title>
 4 
 5 #title的name值
 6 print(soup.title.name)
 7 # u'title'
 8 
 9 #title中的字符串String
10 print(soup.title.string)
11 # u'The Dormouse's story'
12 
13 #title的父亲节点的name属性
14 print(soup.title.parent.name)
15 # u'head'
16 
17 #文档的第一个找到的段落
18 print(soup.p)
19 # <p class="title"><b>The Dormouse's story</b></p>
20 
21 #找到的p的class属性值
22 print(soup.p['class'])
23 # u'title'
24 
25 #找到a标签
26 print(soup.a)
27 # http://example.com/elsie" id="link1">Elsie
28 
29 #找到所有的a标签
30 print(soup.find_all('a'))
31 # [http://example.com/elsie" id="link1">Elsie,
32 #  http://example.com/lacie" id="link2">Lacie,
33 #  http://example.com/tillie" id="link3">Tillie]
34 
35 #找到id值等于3的a标签
36 print(soup.find(id="link3"))
37 # http://example.com/tillie" id="link3">Tillie

从文档中找到所有<a>标签的链接:

1 for link in soup.find_all('a'):
2     print(link.get('href'))
3     # http://example.com/elsie
4     # http://example.com/lacie
5     # http://example.com/tillie

从文档中获取所有文字内容:

print(soup.get_text())

The Dormouse's story

The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie,
Lacie and
Tillie;
and they lived at the bottom of a well.
...

 对象的种类

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

  • Tag:和html中的Tag基本没有区别,可以简单上手使用

  • NavigableString: 被包裹在tag内的字符串

  • BeautifulSoup: 表示一个文档的全部内容,大部分的时候可以把他看做一个tag对象,支持遍历文档树和搜索文档树方法。

  • Comment:这是一个特殊的NavigableSting对象,在出现在html文档中时,会以特殊的格式输出,比如注释类型。

 搜索文档树的最简单的方法就是搜索你想获取tag的的name:

1 soup.head
2 # <head><title>The Dormouse's story</title></head>
3 
4 soup.title
5 # <title>The Dormouse's story</title>

如果你还想更深入的获得更小的tag:例如我们想找到body下的被b标签包裹的部分

1 soup.body.b
2 # <b>The Dormouse's story</b>

获取所有的标签,这个时候需要find_all()方法,他返回一个列表类型。

tag=soup.find_all('a')  #返回的是列表
# [<a   href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a   href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a   href="http://example.com/tillie" id="link3">Tillie</a>]

#假设我们要找到a标签中的第二个元素:
need = tag[1]
#简单吧

子节点

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

 1 head_tag = soup.head
 2 head_tag
 3 # <head><title>The Dormouse's story</title></head>
 4 
 5 head_tag.contents
 6 [<title>The Dormouse's story</title>]
 7 title_tag = head_tag.contents[0]
 8 print(title_tag)
 9 # <title>The Dormouse's story</title>
10 title_tag.contents
11 # [u'The Dormouse's story']
  • 另外通过tag的 .children生成器,可以对tag的子节点进行循环:
1 for child in title_tag.children:
2     print(child)
3     # The Dormouse's story
  • 这种方式只能遍历出子节点。如何遍历出子孙节点呢?

子孙节点:比如 head.contents 的子节点是<title>The Dormouse's story</title>,这里 title本身也有子节点:‘The Dormouse‘s story’ 。这里的‘The Dormouse‘s story’也叫作head的子孙节点.

1 for child in head_tag.descendants:
2     print(child)
3     # <title>The Dormouse's story</title>
4     # The Dormouse's story

找到tag下的所有的文本内容

  1. 如果该tag只有一个子节点(NavigableString类型):直接使用tag.string就能找到。
  2. 如果tag有很多个子、孙节点,并且每个节点里都string:

我们可以用迭代的方式将其全部找出:

 1 for string in soup.strings:
 2     print(repr(string))
 3     # u"The Dormouse's story"
 4     # u'

'
 5     # u"The Dormouse's story"
 6     # u'

'
 7     # u'Once upon a time there were three little sisters; and their names were
'
 8     # u'Elsie'
 9     # u',
'
10     # u'Lacie'
11     # u' and
'
12     # u'Tillie'
13     # u';
and they lived at the bottom of a well.'
14     # u'

'
15     # u'...'
16     # u'
'

输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容:(全部是空格的行会被忽略掉,段首和段末的空白会被删除)

 1 for string in soup.stripped_strings:
 2     print(repr(string))
 3     # u"The Dormouse's story"
 4     # u"The Dormouse's story"
 5     # u'Once upon a time there were three little sisters; and their names were'
 6     # u'Elsie'
 7     # u','
 8     # u'Lacie'
 9     # u'and'
10     # u'Tillie'
11     # u';
and they lived at the bottom of a well.'
12     # u'...'

父节点

继续分析文档树,每个tag或字符串都有父节点:被包含在某个tag中

.parent

通过 .parent 属性来获取某个元素的父节点.在例子的文档中,<head>标签是<title>标签的父节点:

1 title_tag = soup.title
2 title_tag
3 # <title>The Dormouse's story</title>
4 title_tag.parent
5 # <head><title>The Dormouse's story</title></head>

文档title的字符串也有父节点:<title>标签

1 title_tag.string.parent
2 # <title>The Dormouse's story</title>

文档的顶层节点比如<html>的父节点是 BeautifulSoup 对象:

1 html_tag = soup.html
2 type(html_tag.parent)
3 # <class 'bs4.BeautifulSoup'>

BeautifulSoup 对象的 .parent 是None:

1 print(soup.parent)
2 # None

.parents

通过元素的 .parents 属性可以递归得到元素的所有父辈节点,下面的例子使用了 .parents方法遍历了<a>标签到根节点的所有节点.

 1 link = soup.a
 2 link
 3 # <a   href="http://example.com/elsie" id="link1">Elsie</a>
 4 for parent in link.parents:
 5     if parent is None:
 6         print(parent)
 7     else:
 8         print(parent.name)
 9 # p
10 # body
11 # html
12 # [document]
13 # None

有关兄弟节点、回退和前进以及等内容和子节点、父节点差不多,详情请参考官方文档

免责声明:文章转载自《BS4》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇redis 模糊搜索Linux_网络基础管理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

OpenWrt路由器通过LuCI界面实现Guest SSID功能

此外,OpenWrt路由器上的访客SSID不会受到主SSID的MAC地址过滤功能的影响,这是番茄路由器的优势。...

mini.DataGrid使用说明

√√√ ajaxOptionsObjectajax配置对象。√√√ idFieldString是行数据的唯一字段。设置为“client”之后,客户端将排序√√√√ totalCountNumber记录总数√√√ defaultColumnWidthNumber默认列宽100√√√√ showColumnsBoolean显示标头true√√√√ showPag...

Element UI 弹窗(Dialog)改成自适应高度,仅body内容部分滚动

定义样式如下:.abow_dialog{display:flex;justify-content:center;align-items:Center;overflow:hidden;.el-dialog{margin:0auto!important;height:90%;overflow:hidden;.el-dialog__body{position:ab...

Centos-修改文件访问和修改时间-touch

触摸如果文件存在,请更改文件的访问时间和修改时间。如果不存在,请创建一个空的文件相关选项。a将文件访问时间更改为当前系统时间。m将文件修改时间更改为当前系统时间。c如果文件不存在,请不要创建它。d不提示。d指定日期和时间。格式为Y-m-dH:m:S-r递归修改目录下的所有文件和内容...

解决Maven无法下载fastdfs-client-java依赖,Dependency 'org.csource:fastdfs-client-java:1.27-SNAPSHOT' not found.

然后,您成功地将fastdfs客户端java打包到本地Maven仓库,更新项目Maven,pom.xml文件将不会找不到fastdfs客户机java依赖项。...

Systemd简介与使用

Systemd在并行启动中采用了比Upstart更激进的方案。图2显示了systemd的并行启动模式。它允许所有配置的服务同时启动。事实上,大多数使用systemd的现代发行版都与此类似。系统通过配置这些单元来切换和管理服务。...