解析数据的Beautiful Soup 模块(一)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 解析数据的Beautiful Soup 模块(一)

使用Beautiful Soup解析数据

Beautiful Soup是一个用于从HTML和XML文件中提取数据的Python模块。Beautiful Soup提供一些简单的函数用来处理导航、搜索、修改分析树等功能。Beautiful Soup 模块中的查找提取功能非常强大,而且非常便捷。Beautiful Soup自动输入文档转换为Unicode编码,输出文档转换为UTF-8编码。开发者不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。

Beautiful Soup 的安装

目前推荐使用的是Beautiful Soup 4, 已经被移植到bs4当中,需要from bs4 然后导入Beautiful Soup。

pip install bs4

解析器

Beautiful Soup支持Python标准库中包含的HTML解析器,但它也支持许多第三方Python解析器,其中包含lxml解析器。根据不同的操作系统,您可以使用以下命令之一安装lxml:

§ apt-get install python-lxml

§ easy_install lxml

§ pip install lxml

另一个解析器是html5lib,它是一个用于解析HTML的Python库,按照Web浏览器的方式解析HTML。您可以使用以下命令之一安装html5lib:

§ apt-get install python-html5lib

§ easy_install html5lib

§ pip install html5lib

关于每个解析器的优缺点如下表:
image.png

Beautiful Soup安装完成以后,下面将将介绍如何通过Beautiful Soup 库进行HTML的解析工作,具体示例步骤如下:

(1)导入bs4库,然后创建一个模拟HTML代码的字符串,代码如下:

# 作者      :liuxiaowei
# 创建时间   :2/5/22 9:25 PM
# 文件      :使用BeautifulSoup解析HTML代码.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
"""

(2)创建BeautifulSoup对象,并指定解析器为lxml,最后通过打印的方式将解析的HTML代码显示在控制台当中,代码如下:

# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup)                  # 打印解析的HTML代码
print(type(soup))            # 打印数据类型

程序运行结果如下:

<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>

<class 'bs4.BeautifulSoup'>

说 明

如果将html_doc字符串中的代码,保存在index.html文件中,可以通过打开HTML文件的方式进行代码解析,并且可以通过prettify()方法进行代码的格式化处理,代码如下:

with open('index.html', 'w') as f:
  f.write('html_doc')
soup = BeautifulSoup(open("index.html"), "lxml")
print(soup.prettify())

获取节点内容

使用Beautiful Soup 可以直接调用节点的名称,然后再调用对应的string属性便可以获取到节点内的文本信息。在单个节点结构层次非常清晰的情况下,使用这种方式提取节点信息的速度是非常快的。

获取节点对应的代码

示例代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/5/22 9:25 PM
# 文件      :使用BeautifulSoup解析HTML代码.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文

with open('index.html', 'w') as f:
    f.write(html_doc)
soup = BeautifulSoup(open('index.html'), "lxml")
print(soup.prettify())

程序运行结果如下:

head节点内容为:

<head>
<title>第一个 HTML 页面</title>
</head>
body节点内容为:
 <body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
title节点内容为:
 <title>第一个 HTML 页面</title>
p节点内容为:
 <p>body 元素的内容会显示在浏览器中。</p>

注 意

在打印p节点对应的代码时,会发现只打印了第一个P节点内容,这说明当多个节点时,该选择方式只会获取第一个节点中的内容,其他后面的节点将被忽略。

说 明

除了通过制订节点名称的方式获取节点内容以外,还可以使用name属性获取节点的名称,示例代码如下:

# 获取节点名称
print(soup.head.name)
print(soup.body.name)
print(soup.title.name)
print(soup.p.name)

程序运行结果如下:

head
body
title
p

获取节点属性

每个节点可能都会含有多个属性,例如, class或者id等。如果已经选择了一个指定的节点名称,那么只需要调用attrs即可获取这个节点下的所有属性。代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/6/22 10:17 AM
# 文件      :获取节点属性.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>横排响应式登录</title>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <meta name="viewport" content="width=device-width"/>
    <link href="font/css/bootstrap.min.css" type="text/css" rel="stylesheet">
    <link href="css/style.css" type="text/css" rel="stylesheet">
</head>
<body>
<h3>登录</h3>
<div class="glyphicon glyphicon-envelope"><input type="text" placeholder="请输入邮箱"></div>
<div class="glyphicon glyphicon-lock"><input type="password" placeholder="请输入密码"></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('meta节点中属性如下:\n',soup.meta.attrs)
print('link节点中属性如下:\n',soup.link.attrs)
print('div节点中属性如下:\n',soup.div.attrs)
print('div节点中input属性如下:\n', soup.div.input.attrs)

程序运行结果如下:

meta节点中属性如下:

{
   'http-equiv': 'Content-Type', 'content': 'text/html', 'charset': 'utf-8'}

link节点

div节点中属性如下:

{
   'class': ['glyphicon', 'glyphicon-envelope']}

div节点中input属性如下:

{'type': 'text', 'placeholder': '请输

在以上的运行结果中可以发现,attrs的返回结果为字典类型,字典中的元素分别是对应属性名称与对应的值。所以

在attrs后面添加[]括号并在括号内添加属性名称即可获取指定属性对应的值。代码如下:

print('meta节点中http-equiv属性对应的值为:', soup.meta.attrs['http-equiv'])
print('link节点中href属性对应的值为:', soup.link.attrs['href'])
print('div节点中class属性对应的值为:', soup.div.attrs['class'])

程序运行结果如下:

meta节点中http-equiv属性对应的值为: Content-Type
link节点中href属性对应的值为: font/css/bootstrap.min.css
div节点中class属性对应的值为: ['glyphicon', 'glyphicon-envelope']

在获取节点中指定属性所对应的值时,除了使用上面的方式外,还可以不写attrs,直接在节点后面以中括号的形式直接添加属性名称,来获取对应的值。代码如下:

print('meta节点中http-equiv属性对应的值为:', soup.meta['http-equiv'])
print('link节点中href属性对应的值为:', soup.link['href'])
print('div节点中class属性对应的值为:', soup.div['class'])

获取节点包含的文本内容

实现获取节点包含的文本内容是非常简单的,只需要在节点名称后面添加string属性即可。代码如下:

print('title节点内包含的文本内容为:', soup.title.string)
print('h3节点所包含的文本内容为:', soup.h3.string)

程序运行结果如下:

title节点内包含的文本内容为: 横排响应式登录

h3节点所包含的文本内容为: 登录

嵌套获取节点内容

HTML代码中的每个节点都会出现嵌套的可能,而使用Beautiful Soup获取每个节点的内容时,以通过“."直接获取下一个节点中的内容(当前节点的子节点)。代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/6/22 11:49 AM
# 文件      :获取嵌套节点内容.py
# IDE      :PyCharm

from bs4 import BeautifulSoup # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>横排响应式登录</title>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <meta name="viewport" content="width=device-width"/>
    <link href="font/css/bootstrap.min.css" type="text/css" rel="stylesheet">
    <link href="css/style.css" type="text/css" rel="stylesheet">
</head>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('head节点内容如下:\n',soup.head)
print('head节点数据类型为:',type(soup.head))
print('head节点中title节点内容如下:\n',soup.head.title)
print('head节点中title节点数据类型为:',type(soup.head.title))
print('head节点中title节点中的文本内容为:',soup.head.title.string)
print('head节点中title节点中文本内容的数据类型为:',type(soup.head.title.string))

程序运行结果如下:

head节点内容如下:

<head>
<title>横排响应式登录</title>
<meta charset="utf-8" content="text/html" http-equiv="Content-Type"/>
<meta content="width=device-width" name="viewport"/>
<link href="font/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="css/style.css" rel="stylesheet" type="text/css"/>
</head>

head节点数据类型为:

head节点中title节点内容如下:

head节点中title节点数据类型为:

head节点中title节点中的文本内容为: 横排响应式登录

head节点中title节点中文本内容的数据类型为:

说 明

在上面的运行结果中可以看出,在获取head与其内部的title节点内容时数据类型均为““,也就说明在Tag类型的基础上可以获取当前节点的子节点内容,这样的获取方式叫做嵌套获取节点内容。

关联获取

在获取节点内容时,不一定都能做到一步获取指定节点中的内容,有时还需要先确认某一个节点,然后以该节点为中心获取对应的子节点、孙节点、父节点以及兄弟节点。

• 1、获取子节点

在获取某节点下面的所有子节点时,可以使用contents或者是children属性来实现,其中contents返回的是一个列表,在这列表中的每个元素都是一个子节点内容,而children返回的则是一个"list_iterator"类型的可迭代对象。获取所有子节点的代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/6/22 1:18 PM
# 文件      :实现获取某节点下所有子节点内容.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.head.contents)           # 列表形式打印head下所有子节点
print(soup.head.children)           # 可迭代对象形式打印head下所有子节点

程序运行结果如下:

['\n', <title>关联获取演示</title>, '\n', <meta charset="utf-8"/>, '\n']
<list_iterator object at 0x7f7cf94fcfa0>

从上面结果可以看出,通过head.contents所获取的所有子节点中有三个换行符\n以及两个子标题(title与meta)对应的所有内容。head.children所获取的则是一个’list_iterator’可迭代对象,如果需要的获取该对象中的所有内容可以直接将其转换为list类型或者通过for循环遍历的方式进行获取。代码如下:

print(list(soup.head.children))      # 打印将可迭代对象转换为列表形式的所有子节点
for i in soup.head.children:    # 循环遍历可迭代对象中的所有子节点
  print(i)                # 打印子节点内容

程序运行结果如下:

['\n', <title>关联获取演示</title>, '\n', <meta charset="utf-8"/>, '\n']


<title>关联获取演示</title>


<meta charset="utf-8"/>

• 2、获取孙节点

在获取某节点下面所有的子孙节点时,可以使用descendants属性来实现,该属性会返回一个generator对象,获取该对象中的所有内容时,同样可以直接将其转换为list 类型或者通过for循环遍历的方式进行获取。这里以for循环遍历方式为例,代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/6/22 2:06 PM
# 文件      :使用descendants属性获取子孙节点内容.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
…此处省略…
<body>
<div id="test1">
    <div id="test2">
        <ul>
            <li class="test3" value = "user1234">
                此处为演示信息
            </li>
        </ul>
    </div>
</div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.body.descendants)          # 打印body节点下所有子孙节点内容的generator对象
for i in soup.body.descendants:       # 循环遍历generator对象中的所有子孙节点
    print(i)                            # 打印子孙节点内容

程序运行如下:

所有子孙节点内容的generator对象

<generator object Tag.descendants at 0x7ff1b24f3580>

body节点下所有子节点内容

<div id="test1">
<div id="test2">
<ul>
<li class="test3" value="user1234">
                此处为演示信息
            </li>
</ul>
</div>
</div>

body节点下所有孙节点及以下内容

• 3.获取父节点

<div id="test2">
<ul>
<li class="test3" value="user1234">
                此处为演示信息
            </li>
</ul>
</div>


<ul>
<li class="test3" value="user1234">
                此处为演示信息
            </li>
</ul>


<li class="test3" value="user1234">
                此处为演示信息
            </li>

                此处为演示信息

获取父节点有两种方式:一种是通过parent属性直接获取指定节点的父节点内容,还可以 通过parents属性获取指定节点的父节点及以上(祖先节点)内容,只是parents属性会返回一个generator对象,获取该对象中的所有内容时,同样可以直接将其转换为list类型或者通过for 循环遍历的方式进行获取。这里以for循环遍历方式为例,代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/6/22 2:34 PM
# 文件      :获取父节点及祖先节点内容.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.title.parent)                # 打印title节点的父节点内容
print(soup.title.parents)               # 打印title节点的父节点及以上内容的generator对象
for i in soup.title.parents:           # 循环遍历generator对象中的所有父节点及以上内容
    print(i.name)                       # 打印父节点及祖先节点名称

直接获取title节点的父节点内容

<head>
<title>关联获取演示</title>
<meta charset="utf-8"/>
</head>

父节点及以上内容的generator对象

<generator object PageElement.parents at 0x7fb0b8df36d0>

循环遍历父节点及祖先节点的名称

head
html
[document]

说 明

在上面的运行结果可以看出,parents属性所获取父节点的顺序为head,html,最后的[document]表示文档对象,既是整个HTML文档,也是BeautifulSoup对象。

• 4、获取兄弟节点

兄弟节点也就是同级节点,表示在同一级节点内的所有子节点间的关系。如,在一段HTML代码中获取第一个p节点的下一个div兄弟节点时可以使用next_sibling属性,如果想获取当前div节点的上一个兄弟节点p时可以使用previous_sibling属性。通过这两个属性获取兄弟节点时,如果两个节点之间含有换行符(\n)、空字符或者是其他文本内容时,将返回这些文本节点。代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/6/22 8:16 PM
# 文件      :获取兄弟节点.py
# IDE      :PyCharm

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
<body>
<p class="p-1" value = "1"><a href="https://item.jd.com/12353915.html">零基础学Python</a></p>
第一个p节点下文本
<div class="div-1" value = "2"><a href="https://item.jd.com/12451724.html">Python从入门到项目实践</a></div>
<p class="p-3" value = "3"><a href="https://item.jd.com/12512461.html">Python项目开发案例集锦</a></p>
<div class="div-2" value = "4"><a href="https://item.jd.com/12550531.html">Python编程锦囊</a></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.p.next_sibling)               # 打印第一个p节点下一个兄弟节点(文本节点内容)
print(list(soup.p.next_sibling))         # 以列表形式打印文本节点中的所有元素
div = soup.p.next_sibling.next_sibling  # 获取p节点同级的第一个div节点
print(div)                               # 打印第一个div节点内容
print(div.previous_sibling)              # 打印第一个div节点上一个兄弟节点(文本节点内容)

程序运行结果,第一个p节点的下一个兄弟节点:

第一个p节点下文本

文本节点中的所有元素

['\n', '第', '一', '个', 'p', '节', '点', '下', '文', '本', '\n']

第一个div节点内容

<div class="div-1" value="2"><a href="https://item.jd.com/12451724.html">Python从入门到项目实践</a></div>

第一个div节点上一个兄弟节点

第一个p节点下文本

如果想获取当前节点后面的所有兄弟节点时,可以使用next_siblings属性。如果想获取当前节点前面的所有兄弟节点时可以使用previsou_siblings属性。通过这两个属性所获取的节点都将以generator(可迭代对象)的形式返回。在获取节点的内容时,同样可以直接将其转换为list类型或者通过for循环遍历的方式进行获取。这里以转换list类型为例,代码如下:

print('获取p节点后面的所有兄弟节点如下:\n', list(soup.p.next_siblings))
print('获取p节点前面的所有兄弟节点如下:\n', list(soup.p.previous_siblings))

程序运行结果如下:

获取p节点后面的所有兄弟节点如下:

['\n第一个p节点下文本\n', <div class="div-1" value="2"><a href="https://item.jd.com/12451724.html">Python从入门到项目实践</a></div>, '\n', <p class="p-3" value="3"><a href="https://item.jd.com/12512461.html">Python项目开发案例集锦</a></p>, '\n', <div class="div-2" value="4"><a href="https://item.jd.com/12550531.html">Python编程锦囊</a></div>, '\n']

获取p节点前面的所有兄弟节点如下:

使用find()方法获取内容

['\n']

在HTML代码中获取比较复杂的内容时,可以使用find_all()方法与find()方法。调用这些方法,然后传入指定的参数即可灵活的获取节点中的内容。

接下文 解析数据的Beautiful Soup 模块(二)https://developer.aliyun.com/article/1617922

相关文章
|
21天前
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
3960 5
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
11天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
32 2
|
17天前
|
JavaScript API 开发工具
<大厂实战场景> ~ Flutter&鸿蒙next 解析后端返回的 HTML 数据详解
本文介绍了如何在 Flutter 中解析后端返回的 HTML 数据。首先解释了 HTML 解析的概念,然后详细介绍了使用 `http` 和 `html` 库的步骤,包括添加依赖、获取 HTML 数据、解析 HTML 内容和在 Flutter UI 中显示解析结果。通过具体的代码示例,展示了如何从 URL 获取 HTML 并提取特定信息,如链接列表。希望本文能帮助你在 Flutter 应用中更好地处理 HTML 数据。
99 1
|
28天前
|
XML 前端开发 数据格式
Beautiful Soup 解析html | python小知识
在数据驱动的时代,网页数据是非常宝贵的资源。很多时候我们需要从网页上提取数据,进行分析和处理。Beautiful Soup 是一个非常流行的 Python 库,可以帮助我们轻松地解析和提取网页中的数据。本文将详细介绍 Beautiful Soup 的基础知识和常用操作,帮助初学者快速入门和精通这一强大的工具。【10月更文挑战第11天】
56 2
|
17天前
|
JSON 前端开发 JavaScript
API接口商品详情接口数据解析
商品详情接口通常用于提供特定商品的详细信息,这些信息比商品列表接口中的信息更加详细和全面。以下是一个示例的JSON数据格式,用于表示一个商品详情API接口的响应。这个示例假定API返回一个包含商品详细信息的对象。
|
29天前
|
JSON 前端开发 JavaScript
前端模块打包器的深度解析
【10月更文挑战第13天】前端模块打包器的深度解析
|
29天前
|
缓存 前端开发 JavaScript
Webpack技术深度解析:模块打包与性能优化
【10月更文挑战第13天】Webpack技术深度解析:模块打包与性能优化
|
30天前
|
API
Vue3组件通信全解析:利用props、emit、provide/inject跨层级传递数据,expose与ref实现父子组件方法调用
Vue3组件通信全解析:利用props、emit、provide/inject跨层级传递数据,expose与ref实现父子组件方法调用
388 0
|
3天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
14 2
|
1月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
66 0

推荐镜像

更多