BeautifulSoup模块

【一】Beautifulsoup4初始

【前言】bs4模块

  • 安装

pip install beautifulsoup4

【1】什么是beautifulsoup:

​ 是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。(官方)

​ beautifulsoup是一个解析器,可以特定的解析出内容,省去了我们编写正则表达式的麻烦。

  • 模块介绍

BeautifulSoup是一个解析库,可以从HTLML中提取数据的库

【2】HTML解析器

【1】内置解析器html.parser

  • Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器
  • 如果我们不安装它,则 Python 会使用 Python默认的解析器
soup=BeautifulSoup(页面源码,'html.parser') 

【2】第三方解析器lxml

  • lxml 解析器更加强大,速度更快,推荐安装。
pip3 install lxml
  • 语法
soup=BeautifulSoup(页面源码,'lxml') 

【3】第三方解析器html5lib

  • 另一个可供选择的解析器是纯Python实现的 html5lib
  • html5lib的解析方式与浏览器相同
  • 可以选择下列方法来安装html5lib
pip3 install html5lib
  • 语法
soup=BeautifulSoup(页面源码,'html5lib') 

【4】解析器对比

(1)解析器优缺点

1

(2)解析器使用方法
解析器 使用方法 优势 劣势
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语言库
html5lib BeautifulSoup(markup, "html5lib") 最好的容错性 以浏览器的方式解析文档 生成HTML5格式的文档 速度慢 不依赖外部扩展

【3】生成soup对象

  • 从一个soup对象开始,以下两种方式生成一个soup对象

  • soup=beautifulsoup(解析内容,解析器)

  • 常用解析器:html.parser,lxml,xml,html5lib

  • 有时候需要安装安装解析器:比如pip3 install lxml

【1】方法一

from bs4 import BeautifulSoup

# 指定HTML源码文件,传入文件源码
soup = BeautifulSoup(open("index.html"))   

【2】方法二

from bs4 import BeautifulSoup

# 直接放入 HTML 源码
soup = BeautifulSoup("<html>data</html>")  

【3】示例

生成 BeautifulSoup 对象有两种常用的方法:

通过解析器直接解析字符串或文件内容:

from bs4 import BeautifulSoup

# 通过字符串生成soup对象
html_content = "<html><body><h1>Hello, World!</h1><p>This is an example paragraph.</p></body></html>"
soup = BeautifulSoup(html_content, 'html.parser')

# 通过文件生成soup对象
with open("example.html") as file:
    soup = BeautifulSoup(file, 'html.parser')

通过请求库获取网页内容并解析:

import requests
res = requests.get('https://www.biqg.cc/book/3525/', timeout=3)

headers = {
   
    "User-Agent": UserAgent().random
}
# 指定HTML源码文件,传入文件源码
soup = BeautifulSoup(res.text, 'html.parser')
  • 使用标签名来获取结点:

soup.标签名

  • 使用标签名来获取结点标签名(这个重点是name,主要用于非标签名式筛选时,获取结果的标签名):

soup.标签.name

  • 使用标签名来获取结点属性:

soup.标签.attrs(获取全部属性)

soup.标签.attrs[属性名](获取指定属性)

soup.标签[属性名](获取指定属性)

soup.标签.get(属性名)

  • 使用标签名来获取结点的文本内容:

soup.标签.text

soup.标签.string

soup.标签.get_text()

补充1:

上面的筛选方式可以使用嵌套:

print(soup.p.a)#p标签下的a标签

# 获取源码中所有的文本内容
text = soup.get_text() 
# 获取源码中所有的a标签
a_tag = soup.find_all('a')
# 遍历每一个a标签
for a in a_tag:
    # 提取每一个a标签中的 href 属性
    a_href = a.get("href")

【二】文档树操作

【1】什么是文档树

​ BeautifulSoup的文档树是指使用BeautifulSoup解析HTML或XML文档后所构建的数据结构,它代表了整个文档的层级结构和内容关系。在BeautifulSoup中,文档树以特定的方式组织了文档中的各个元素(标签、文本、注释等),使得用户可以方便地对文档进行遍历、搜索和操作。

image-20240329110839808

【2】常见的文档树遍历算法

  • 选择起始节点:
    • 首先需要确定遍历的起始节点,可以是整个文档的根节点,也可以是某个指定的节点。
  • 访问当前节点:
    • 从起始节点开始,首先访问当前节点,可以获取当前节点的标签名、属性、文本内容等信息。
  • 处理当前节点:
    • 根据需要,对当前节点进行一些处理操作,比如判断节点类型、执行特定的任务等。
  • 遍历子节点:
    • 如果当前节点有子节点,将从第一个子节点开始递归遍历,重复步骤2和步骤3。
  • 遍历兄弟节点:
    • 如果当前节点没有子节点或者子节点已经遍历完毕,将继续遍历当前节点的下一个兄弟节点,重复步骤2和步骤3。
  • 返回父节点:
    • 当遍历到某个节点的兄弟节点都被遍历完毕后,返回到该节点的父节点,并继续遍历父节点的下一个兄弟节点。
  • 结束条件:
    • 当整个文档树的节点都被遍历完毕,或者满足某个结束条件时,结束遍历过程。

总结

​ 深度优先搜索(DFS)和广度优先搜索(BFS)。这两种搜索算法在处理文档树时具有不同的特点和应用场景:

  1. 深度优先搜索(DFS):
    • 从起始节点开始,尽可能深地访问每个节点的子节点,直到到达最深层的节点。
    • 使用递归或栈来实现,适合于需要优先探索整棵子树的情况。
    • 对于HTML/XML文档DOM树,DFS可以帮助我们深入到每个节点的子节点,适用于深度优先遍历和搜索。
  2. 广度优先搜索(BFS):
    • 从起始节点开始,按层级顺序逐层访问各个节点,先访问完当前层的所有节点,再逐层向下遍历。
    • 使用队列来实现,适合于需要逐层扩展搜索范围的情况。
    • 在处理HTML/XML文档DOM树时,BFS可以帮助我们逐层遍历节点,适用于广度优先遍历和搜索。

​ 选择DFS还是BFS取决于具体的需求和应用场景。DFS适合于深入探索子树,而BFS适合于逐层扩展搜索范围。

from bs4 import BeautifulSoup
html = """
<html >
<head>
<meta charset="UTF-8">
<title>this is a title</title>
</head>
<body>
<p class="news">123</p>
<p class="contents" id="i1">456</p>
<a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >advertisements</a>
</body>
</html>
"""
soup = BeautifulSoup(html,'lxml')
print("获取结点".center(50,'-'))
print(soup.head)#获取head标签
print(soup.p)#返回第一个p标签
#获取结点名
print("获取结点名".center(50,'-'))
print(soup.head.name)
print(soup.find(id='i1').name)
#获取文本内容
print("获取文本内容".center(50,'-'))
print(soup.title.string)#返回title的内容
print(soup.title.text)#返回title的内容
print(soup.title.get_text())
#获取属性
print("-----获取属性-----")
print(soup.p.attrs)#以字典形式返回标签的内容
print(soup.p.attrs['class'])#以列表形式返回标签的值
print(soup.p['class'])#以列表形式返回标签的值
print(soup.p.get('class'))

#############
t=soup.title
print(type(t))#<class 'bs4.element.Tag'>
print(t.name)#title
print(t.text)

#嵌套选择:
print(soup.head.title.string)

【5】遍历文档树的语法:

  1. 子节点和子孙节点的遍历:
    • 使用.contents可以获取子节点列表,例如:soup.body.contents
    • 使用.children可以获取子节点的迭代器,例如:for child in soup.body.children:
    • 使用.descendants可以递归获取所有子孙节点,例如:for descendant in soup.body.descendants:
  2. 父节点和祖先节点的遍历:
    • 使用.parent可以获取父节点,例如:soup.title.parent
    • 使用.parents可以获取所有祖先节点,例如:for parent in soup.title.parents:
  3. 兄弟节点的遍历:
    • 使用.next_sibling.previous_sibling可以获取下一个兄弟节点和上一个兄弟节点。
    • 使用.next_siblings.previous_siblings可以获取所有后续兄弟节点和前序兄弟节点。
  4. 查找特定节点:
    • 使用.find()可以查找符合条件的第一个节点,例如:soup.find('p', class_='news')
    • 使用.find_all()可以查找符合条件的所有节点,例如:soup.find_all('p')
  5. CSS选择器:
    • 使用类似CSS选择器的语法来查找节点,例如:soup.select('p.contents')

【6】遍历文档树

直接通过标签名字选择,特点是速度快,但是如果存在多个相同的标签则只返回第一个

  • html文档准备
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p id="my_p" class="title">hello<b id="bbb" class="boldest">The Dormouse's story</b>
</p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a><a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
  • 文档容错能力,不是一个标准的html也能解析
# 上述html文档的html body标签并没有闭合
soup=BeautifulSoup(html_doc,'lxml')
  • 遍历文档树用法

获取标签内的数据

head = soup.head (head是标签对象)
print(head)

获取标签名称

print(head.name)

获取标签的属性,属性可能有多个,放在列表中

p = soup.body.p # 获取body标签下的p标签
print(p.attrs)  # 获取p标签的属性/id等
print(p.attrs.get('class'))  # 获取p标签的属性方式一,得到的结果是一个列表
print(p.get('class'))  # 获取p标签的属性方式方式二,得到的结果是一个列表
print(p['class'])  # 获取p标签的属性方式方式二,得到的结果是一个列表

嵌套选择

a=soup.body.a
print(a.get('id'))
# 子节点、子孙节点
print(soup.p.contents) #p下所有子节点
print(soup.p.children) #得到一个迭代器,包含p下所有子节点
print(list(soup.p.children)) #得到一个迭代器,包含p下所有子节点
# 父节点、祖先节点
print(soup.a.parent) #获取a标签的父节点(只有一个)
print(soup.p.parent) #获取p标签的父节点
print(soup.a.parents) #找到a标签所有的祖先节点,父亲的父亲,父亲的父亲的父亲...
print(list(soup.a.parents))#找到a标签所有的祖先节点,父亲的父亲,父亲的父亲的父亲...
print(len(list(soup.a.parents)))#找到a标签所有的祖先节点,父亲的父亲,父亲的父亲的父亲...
# 兄弟节点
print(soup.a.next_sibling) #下一个兄弟
print(soup.a.previous_sibling) #上一个兄弟

print(list(soup.a.next_siblings)) #下面的兄弟们=>生成器对象
print(list(soup.a.previous_siblings)) #上面的兄弟们=>生成器对象

【7】搜索文档树

【1】 find_all

find():只返回找到的第一个

find_all():找到的所有

find_all() 方法的用法如下:

  • soup.find_all(name, attrs, recursive, text, limit, **kwargs)
    

    :根据给定的条件查找符合条件的所有元素。

    • name:指定要查找的标签名称。
    • attrs:以字典形式指定要查找的标签的属性和属性值。
    • recursive:指定是否递归搜索子孙节点,默认为 True。
    • text:指定要搜索的文本内容。
    • limit:限制返回结果的数量。
    • **kwargs:其他关键字参数,用于匹配标签的其他属性。
  1. 通过标签名搜索:

    soup.find_all('a')  # 查找所有的<a>标签
    soup.find('div')     # 查找第一个<div>标签
    
  2. 通过CSS类名搜索:

    soup.find_all(class_='class_name')
    
    soup.find_all(class_='header wap_none')
    # 查找所有具有指定类名的标签
    
  3. 通过id搜索:

    soup.find_all(id='element_id')  
    
    # 目标地址
    res = requests.get('https://so.gushiwen.cn/gushi/tangshi.aspx')
    # HTML文本进行解析,创建一个BeautifulSoup对象soup
    soup = BeautifulSoup(res.text, 'html.parser')
    # 查找所有id为'arc-body'的标签
    ids = soup.find_all(id='threeWeixin2')
    print(ids)
    # 查找所有具有指定id的标签
    
  4. 通过属性值搜索:

    soup.find_all(attrs={
         'attribute_name': 'value'})  # 查找所有具有指定属性值的标签
    
    a = soup.find_all('div', attrs={
         'class': 'book'})
    
    print(a)
    
  5. 通过文本内容搜索:

    soup.find_all(text='some text')  # 查找所有包含指定文本内容的标签
    

【2】find

  • find() 方法用于在文档中查找符合条件的tag,并返回第一个匹配的结果。
  • 它可以通过指定name、attrs、recursive和string等参数来过滤查找结果。
find( name , attrs , recursive , string , **kwargs )
  • name: 指定要查找的tag名称,可以是字符串或正则表达式。
  • attrs: 指定tag的属性,可以是字典或字典的列表。
  • recursive: 指定是否递归查找子孙tag,默认为True。
  • string: 指定查找的文本内容,可以是字符串或正则表达式。

【3】find_all()find() 的区别

find_all()find() 都是 BeautifulSoup 中用于查找节点的方法,它们之间的区别在于:

  1. find_all(): 用于查找符合条件的所有节点,并以列表形式返回结果。
  2. find(): 用于查找符合条件的第一个节点,并直接返回该节点对象。
  • 唯一的区别是
    • find_all() 方法的返回结果是值包含一个元素的列表
      • find() 方法直接返回结果
      • find_all() 方法没有找到目标是返回空列表
        • find() 方法找不到目标时,返回 None

【4】五种过滤器

  • 字符串过滤:过滤内容是字符串
a = soup.find(name='a')
print(a) # <a class="

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/564370.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

贪吃蛇的简单实现(c语言)

前言&#xff1a;学完了C语言的基础语法&#xff0c;和一点数据结构的知识&#xff0c;拿贪吃蛇来练练手&#xff0c;并熟悉以前的知识。写完之后&#xff0c;有一种成就感&#xff0c;为以后的学习饱满激情。 注意这里的讲解是由部分到整体的思路。 目录 控制台不能是终端&am…

java可盈保险合同管理系统的设计与实现(springboot+mysql源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的可盈保险合同管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于Spring Boot的…

麒麟服务器操作系统自动化安装应答文件制作

原文链接&#xff1a;麒麟服务器操作系统自动化安装应答文件制作 Hello&#xff0c;大家好啊&#xff01;今天我们将探讨如何为麒麟服务器操作系统制作自动化安装应答文件。在部署大量服务器时&#xff0c;自动化安装是提高效率和确保安装一致性的关键技术。通过使用应答文件&a…

IEC104协议

1. 简介 IEC104规约是一个广泛应用于电力、城市轨道交通等行业的国际标准。 2. 术语解释 遥脉 (电度量)&#xff1a; 是指对现场某装置所发出的脉冲信号进行周期累计的一种远程计数操作。 其实&#xff0c;遥脉也可以看成是被具体规定了采用脉冲计数作为测量方法的一种遥测…

JumpServer搭建堡垒机实战

文章目录 第一步、下载安装第二步、访问异常处理【1】docker方式拉取失败 JumpServer是运维人员可连接内部服务器上进行操作&#xff0c;支持Linux等操作系统的管理工具。 第一步、下载安装 curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver/releases/latest/…

基于函数计算FC3.0 部署AI数字绘画stable-diffusion自定义模型

基于函数计算FC3.0 部署AI数字绘画stable-diffusion自定义模型 部署AI数字绘画stable-diffusion曲线救国授权github账号 部署ffmpeg-app-v3总结 在讲述了函数计算FC3.0和函数计算FC2.0的操作界面UI改版以及在函数管理、函数执行引擎、自定义域名、函数授权及弹性伸缩规则方面进…

精灵传信系统/支持对接易支付/网站+小程序双端php源码下载

简介 精灵传信支持在线提交发送短信&#xff0c;查看回复短信&#xff0c;在线购买额度&#xff0c;自定义对接易支付&#xff0c;设置违禁词&#xff0c;支持网站小程序双端。&#xff08;文末下载&#xff09; 演示截图 在数字化浪潮的推动下&#xff0c;技术创新正以前所未…

maven安装和配置

1.下载版本选择 如果使用的是idea的话&#xff0c;需要考虑跟maven的适配问题&#xff0c;从博文maven 与 idea版本不适配问题的思考 得出以下结论&#xff1a; 1.idea 2021兼容maven 3.8.1及以前的所有版本。 2.idea 2020兼容maven 3.6.3及以前的所有版本。 4.idea 2019兼容m…

深度学习基础——循环神经网络的结构及参数更新方式

深度学习基础——循环神经网络的结构及参数更新方式 深度学习领域的一大重要分支是循环神经网络&#xff08;Recurrent Neural Networks&#xff0c;简称RNN&#xff09;&#xff0c;它是一种用于处理序列数据的神经网络结构。与传统的前馈神经网络不同&#xff0c;循环神经网…

江苏瑞达环保科技股份有限公司| 邀您参加2024全国水科技大会暨技术装备成果展览会

—— 展位号:A18 —— 江苏瑞达环保科技股份有限公司是一家致力于环境保护和可持续发展的高新技术企业&#xff0c;专注于环境治理技术研发和环保节能装备制造,为工业企业提供可靠的工程解决方案。2023年&#xff0c;瑞达科技被认定为江苏省省级专精特新企业。 瑞达科技成立于2…

使用【node】创建本地接口

在前端开发的过程中&#xff0c;接口相关的信息一般是由后端处理好返回给前端&#xff0c;但是有时候后端不在的时候想自己写个接口进行测试是非常麻烦的。 node是前端一个不错的写接口工具 一 初始化文件 1 在新建一个空的文件夹node 进入空文件夹在&#xff0c;文件夹的地…

文献速递:深度学习胶质瘤诊断---结合分子亚型分析、分级与胶质瘤的多任务深度学习分割

Title 题目 Combined molecular subtyping, grading, and segmentation of glioma using multi-task deep learning 结合分子亚型分析、分级与胶质瘤的多任务深度学习分割 Abstract 摘要 Accurate characterization of glioma is crucial for clinical decision making. A…

vue项目中基于fabric 插件实现涂鸦画布功能

vue项目中基于fabric 插件实现涂鸦画布功能 一、效果图二、安装依赖三、main.js引入四、主要代码 一、效果图 二、安装依赖 npm install fabric 三、main.js引入 import fabric from fabric Vue.use(fabric);四、主要代码 //封装成了一个组件 <template><el-dialogt…

图片/视频上传(超简单教程)

#应用场景# 该后端开发接口适用 图片/视频上传&#xff0c;返回路径名称场景 1.视频上传 写在Controller层 这里只是一个接收&#xff0c;调用uploadObject方法上传oss public OmsResult<FileUploadDto> goodsUploadVideo(RequestParam(value "file") Mu…

【力扣 Hot100 | 第七天】4.22(找到字符串中所有字母异位词)

文章目录 2.找到字符串中所有字母异位词2.1题目2.2解法&#xff1a;滑动窗口2.2.1解题思路2.2.2代码实现 2.找到字符串中所有字母异位词 2.1题目 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺…

28map,set关联式容器

序列式容器 vector、list、deque(单纯的纯数据) 关联式容器 map、set&#xff0c;哈希&#xff0c;&#xff0c;&#xff0c;(数据之间有很强的关联性,不是单纯的为了存储数据) Set 底层是搜索树&#xff08;红黑树&#xff09; T是key &#xff0c;compare是仿函数&#xff0…

150G全国1米分辨率土地利用数据【2023年】

#1数据摘要 全国1米分辨率土地利用数据 全国范围,分省份分类,1米精度土地利用数据。2023年版本。 数据格式:tif 坐标系:wgs1984 范围:全国各省份 时间:2023年 精度:1米 地类:共计11个地类 中国1m分辨率土地覆盖数据 文件命名与介绍:数据为GeoTIFF栅格格式,每个城市…

lvgl图形化设计工具GUI Guider结合使用

前言 上篇博客整合了lvgl到项目中&#xff0c;采用的是自己编写源码的方式&#xff0c;实现了个简单的界面。实际过程中一般情况开发界面都借助设计工具&#xff0c;这里使用的是gui guider来进行示例记录 项目结构&#xff08;生成代码路径依然放到项目路径下&#xff09; C…

知识图谱的起源与发展

文章目录 知识图谱的发展历史知识图谱的重要性知识图谱与Ontology、语义网络之间的区别知识图谱的定义 知识图谱的发展历史 知识图谱始于20世纪50年代&#xff0c;至今大致分为三个发展阶段&#xff1a;第一阶段 &#xff08;1955年—1977年&#xff09;是知识图谱的起源阶段&a…

ThingsBoard教程(二十九):详细讲解在tb平台下 http协议下的客户端rpc,服务的rpc的使用

客户端rpc 先来说一下简单的客户端rpc, 客户端发起rpc请求,只需要使用post方法调用该接口即可以 http://host:port/api/v1/$ACCESS_TOKEN/rpc请求路径中间的参数 ACCESS_TOKEN 必须是设备的访问令牌。 请求携带的参数如下,二个参数method和params {"method": …