我们已经准备好了,你呢?

2026我们与您携手共赢,为您的企业形象保驾护航!

参考:安装与使用 、官方文档

1、 Soup的简介

Soup 同样具备解析 HTML/XML 的能力,与 lxml 类似,它的核心用途在于处理和获取 HTML/XML 信息。

系统兼容标准库自带的HTML解析工具,也能够适配部分外部提供的解析工具,倘若未进行特定安装,便会启用预设的解析方案,lxml解析方案性能更优,运行效率更高,建议选用lxml解析方案。

Soup会自动将输入文档转为编码格式,输出文档转为utf-8编码格式。你无需考虑编码问题,除非文档没有指定编码,这时 Soup就无法自动识别。只需说明原始编码格式即可。

2、 Soup 安装

Soup 3 现在不再继续维护了,建议当前项目改用 Soup 4

pip3 install beautifulsoup4

3、开启 Soup 之旅

先提供官方文件的网址,资料篇幅偏长,结构也欠清晰,这篇文章将加以梳理,以便于读者查阅。

官方文档

4、创建 Soup 对象

首先必须要导入 bs4 库

from bs4 import BeautifulSoup

我们创建一个字符串,后面的例子我们便会用它来演示

html = """
The Dormouse's story

The Dormouse's story

从前有三个小妹妹,她们的名字是 , Lacie and Tillie; 他们住在井的最深处。

...

"""

创建 对象

解析网页内容,采用lxml作为解析器,创建BeautifulSoup对象

另外,我们还可以用本地 HTML 文件来创建对象,例如

这个名为 soup 的变量,通过调用 open 函数打开 index.html 文件,并使用 lxml 作为解析器特征创建了一个 BeautifulSoup 对象

那个代码片段的作用是读取本地 index.html 文件,然后基于此文件构造 soup 对象

下面我们来打印一下 soup 对象的内容,格式化输出

print(soup.prettify())


 
 
  The Dormouse's story
 
 
 
 

The Dormouse's story

从前有三个小妹妹,她们的名字是 , Lacie and Tillie ; 他们住在井的最深处。

...

这个就是最终呈现的样貌,按照规范排列了它的元素,这种操作很常用,各位朋友需要牢记啊。

5、四大对象种类

Soup能够把复杂的HTML文档变成一个结构繁复的树形体系,这个体系中的每一部分都是一个独立的个体,这些个体都可以被划分成四种类型,

Tag

下面我们进行一一介绍

(1)Tag

Tag指的是什么?简单来说就是网页代码里的一个个标记符号,比如

The Dormouse's story
Elsie

那些位于标题等位置的 HTML 标签,以及它们所包裹的元素,统称为标签集合,现在让我们体验一下如何借助 Soup 来便捷地提取这些标签集合

下面每一段代码中注释部分即为运行结果

print(soup.title)
#The Dormouse's story
 
print(soup.head)
#The Dormouse's story
 
print(soup.a)
#
 
print(soup.p)
#

The Dormouse's story

我们借助 soup 和标签名能够便捷地提取这些标签的信息,是不是觉得比正则表达式更容易呢?不过有一点需要注意,它搜索的是所有内容中首个满足条件的标签,若需检索全部标签,我们将在后续部分进行说明。

我们可以验证一下这些对象的类型

print(type(soup.a))
#

Tag 包含两项关键信息,一项是名称,另一项是属性,接下来我们逐一进行了解

name

print(soup.name)
print(soup.head.name)
#[document]
#head

soup 对象自身具有特殊性,它的名称就是空值,针对其他元素,其返回的内容就是元素所带标签的称号。

attrs

print(soup.p.attrs)
这个对象的类别是标题,它的名称叫做小灰鼠

此处将 p 标签具备的所有性质进行了显示,其呈现形态为一种数据集合。

要取得某个特定特性,可以这样做,比如我们要知道它的 class 名称是什么

获取soup对象中p标签的class属性值,然后进行打印输出
#['title']

还可以这样,利用get方法,传入属性的名称,二者是等价的

输出标签的类别属性值,通过解析文档获取指定元素的属性信息,将结果展示出来
#['title']

我们可以对这些属性和内容等等进行修改,例如

soup对象的属性class赋值为newClass
print(soup.p)
#

The Dormouse's story

还可以对这个属性进行删除,例如

del(soup.p['class'])
print(soup.p)
#

The Dormouse's story

然而,对于修正和移除的功能,并非我们核心应用,因此在此不予详述,如需了解,请参阅先前给出的正式资料。

(2)

既然已经拿到标签信息,那么接下来要考虑的是,如何取得标签里的文字内容呢?这很简单,只需运用点即可,比如

print(soup.p.string)
#The Dormouse's story

我们这就便捷地提取了标签中的信息,试想若借助正则表达式该有多么繁琐。它的属性属于一种,翻译为中文便是可遍历的文本,但最好还是采用它的英文原名。

来检查一下它的类型

print(type(soup.p.string))
#

(3)

该实体涵盖了整个文本资料的全部细节,多数情形下,能够视作标记实体,此标记具备独特性,可以逐一探明它的类别,标签,以及其具备的特征进行一番审视

print(type(soup.name))
#
print(soup.name)
# [document]
print(soup.attrs)
#{} 空字典

(4)

该实体属于一种特殊类别,其展现的信息并不涵盖标记字符,然而若对其缺乏妥善应对,或会引发文本加工环节的潜在难题。

我们找一个带注释的标签

print(soup.a)
print(soup.a.string)
print(type(soup.a.string))

运行结果如下




a 标签中的文字本质上起说明作用,但当我们通过 . 来提取它的内容时,会发现它已经移除了注释标记,这种情况可能会造成一些麻烦。

此外我们进行打印显示其种类,了解到它属于某个类别,因此,在运用时需要先进行验证,验证方法如下

当 soup.a.string 的类型是 bs4.element.Comment 时
  print soup.a.string

在该代码段里,我们首先确认了它的类别,看是否属于指定类别,接着再执行后续步骤,例如显示信息。

6、遍历文档树(1)直接子节点

要点:. . 属性

.

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

print(soup.head.contents)
#[The Dormouse's story]

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

print(soup.head.contents[0])
#The Dormouse's story

.

它给出的并非清单,但能逐个访问所有分支。

我们进行打印,观察后可知,它属于一种列表生成式对象

print(soup.head.children)
#

我们如何取得内部信息呢?非常容易,只需进行遍历即可,具体实现和输出如下

对于soup.body的每一个子元素,进行遍历
  print child

The Dormouse's story

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

...

(2)所有子孙节点

知识点:. 属性

.

. 属性仅囊括tag的直系后代,. 属性则能递归检索所有tag的各级节点,鉴于二者功能相似,也需逐一排查以获取信息。

对于soup的所有后代元素,逐一进行遍历
  print child

执行情况显示,全部节点均已完成输出,首先呈现最外层的 HTML 标记,接着逐个移除 head 标记,然后继续向下处理。

The Dormouse's story

The Dormouse's story

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

...

The Dormouse's story The Dormouse's story The Dormouse's story

The Dormouse's story

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

...

The Dormouse's story

The Dormouse's story The Dormouse's story

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

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

...

...

(3)节点内容

知识点:. 属性

当tag仅含有一个类型子节点时,该tag能通过 . 操作获取子节点。若tag仅有一个子节点,该tag也能应用 . 方法,其输出结果等同于当前唯一子节点的 . 操作结果。

简单来讲,当某个容器里面不再包含其他容器时,点号就会呈现该容器的内部元素。倘若容器仅剩下一个子容器,点号同样会显示最内层的那个子元素。比如

print(soup.head.string)
#The Dormouse's story
print(soup.title.string)
#The Dormouse's story

若tag中嵌套了多个子节点,则tag无法明确,究竟应当调用哪个子节点的信息,其最终返回值将是空。

print(soup.html.string)
# None

(4)多个内容

知识点: . . 属性

.

获取多个内容,不过需要遍历获取,比如下面的例子

for string in soup.strings:
  print(repr(string))
  # u"The Dormouse's story"
  # u'\n\n'
  # u"The Dormouse's story"
  # u'\n\n'
从前有三位小姑娘,她们的名字是
  # u'Elsie'
  # u',\n'
  # u'Lacie'
  # u' and\n'
  # u'Tillie'
他们住在井底,那里是黑暗的深渊。
  # u'\n\n'
  # u'...'
  # u'\n'

.

内容细节十分丰富,涵盖了多个方面,例如人物关系,情节发展,以及环境描写,每个部分都经过精心设计,细节满满,让读者能够深入理解故事背景,感受人物情感变化,体会作者想要表达的主题思想。

对于每一个由soup处理后的字符串,
  print(repr(string))
  # u"The Dormouse's story"
  # u"The Dormouse's story"
从前有三位小姑娘,她们的名字分别是
  # u'Elsie'
  # u','
  # u'Lacie'
  # u'and'
  # u'Tillie'
  那个家伙跟他的家人住在井的最深处。
  # u'...'

(5)父节点

知识点: . 属性

p = soup.p
print(p.parent.name)
#body
 
内容等于解析结果的头部标题文本值
print(content.parent.name)
#title

(6)全部父节点

知识点:. 属性

通过元素的 . 属性可以递归得到元素的所有父辈节点,例如

content = soup.head.title.string
对于内容中的每一个父级元素,
  print parent.name

title
head
html
[document]

(7)兄弟节点

知识点:. . 属性

同级别的节点可以称作兄弟节点,. 属性用来取得当前节点的邻近节点,. 若该节点没有相邻节点,则返回空值。

标签的点和点属性多数情况下是文本或空值,因为空值或换行也能当作一个节点来看待,因此最终的结果可能是空白的或者换行

print(soup.p.next_sibling)
#    实际该处为空白
print(soup.p.prev_sibling)
#None  没有前一个兄弟节点,返回 None
输出 soup 的 p 元素后面紧邻的两个元素的内容
#

Once upon a time there were three little sisters; and their names were #, #Lacie and #Tillie; 他们住在井的最深处,日子一天天过去。

#下一个节点的下一个兄弟节点是我们可以看到的节点

(8)全部兄弟节点

知识点:. . 属性

通过 . 和 . 属性可以对当前节点的兄弟节点迭代输出

对于每一个兄弟元素,在soup.a的后续元素中寻找
  print(repr(sibling))
  # u',\n'
  # Lacie
  # u' and\n'
  # Tillie
他住在井底,日子过得非常艰难。
  # None

(9)前后节点

知识点:. . 属性

它和那个不一样,针对的不是从属的单元,而是包罗万象,不论层级如何

比如 head 节点为

The Dormouse's story

那么它的下一个节点便是 title,它是不分层次关系的

print(soup.head.next_element)
#The Dormouse's story

(10)所有前后节点

知识点:. . 属性

借助 . 和 . 的遍历工具,能够实现文档解析信息的正序或逆序检索,仿佛文档正在实时解析之中

对于最后那个a标签的后续元素,逐一进行遍历
  print(repr(element))
# u'Tillie'
# u';\nand they lived at the bottom of a well.'
# u'\n\n'
# 

...

# u'...' # u'\n' # None

检索文件目录结构,包含名称,属性,空白,文本以及其他参数

() 该方法用来检索当前标签下所有子标签,同时检测它们是否满足筛选标准

1)name 参数

name 参数能够筛选出所有名称为 name 的标签,但字符串类型的对象会被系统自动排除在外

A.传字符串

最基础的一种筛选方式是针对字符串进行操作。在搜索功能里提供一个文本参数, Soup会去寻找与该文本完全一致的元素,接下来的示例将演示如何找出文件内所有具备特定名称的标记

soup.find_all('b')
# [The Dormouse's story]
 
输出所有标签名为a的元素,将结果展示出来
#[, Lacie, Tillie]

B.传正则表达式

若参数为正则表达式,Soup将借助该表达式的match功能进行内容匹配。以下示例旨在找出所有以b开头的标签,这意味着包含该字母的标签都将被识别出来

import re
对于每一个符合正则表达式"^b"的标签,在解析文档中查找,然后遍历
  print(tag.name)
# body
# b

C.传列表

当提供列表作为参数时,Soup将返回所有与列表内任意一项相吻合的内容,下面代码旨在找出文档内全部的标签以及标签名

soup.find_all(["a", "b"])
# [The Dormouse's story,
# Elsie,
# Lacie,
# Tillie]

D.传 True

真值能够对应任何数据,后续脚本寻获全部标记,不过不输出字符构成的部分

对于每一个由soup.find_all(True)找到的标签,
  print(tag.name)
# html
# head
# title
# body
# p
# b
# p
# a
# a

E.传方法

当缺少适用的过滤器时,可以创建一个方法,该方法仅接收一个元素作为输入,若该输入元素符合条件,则方法返回肯定结果,否则返回否定结果

该种方式确认了目标项目,倘若其具备类型标识却不具备唯一编号,便会得出肯定结论:

def has_class_but_no_id(tag):
检查标签是否包含class属性,同时确认不包含id属性

将这个方法作为参数传入 () 方法,将得到所有

二维码
扫一扫在手机端查看

本文链接:https://by928.com/11338.html     转载请注明出处和本文链接!请遵守 《网站协议》
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。

项目经理在线

我们已经准备好了,你呢?

2020我们与您携手共赢,为您的企业形象保驾护航!

在线客服
联系方式

热线电话

13761152229

上班时间

周一到周五

公司电话

二维码
微信
线