Python 网络爬虫从0到1 (4):Beautiful Soup 4库入门详解

2023-12-19 00:20

本文主要是介绍Python 网络爬虫从0到1 (4):Beautiful Soup 4库入门详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  从先前的几篇文章中,我们已经能够使用Requests库构造请求并获得正确的响应,但是在样例中我们也发现了仅使用Requests库的缺陷。在网络爬虫的设计中,仅能构造请求并收到响应是远远不够的。想要获取响应中有意义的信息并能够由此采取下一步行动,是整个流程中的重要一段。所以本篇文章,我们就来一起学习较为流行的HTML/XML数据分析提取库:Beautiful Soup 4

Beautiful Soup 4

Beautiful Soup 4介绍

  Beautiful Soup 4库是一个在Python爬虫设计中非常流行的数据分析提取库。它能够解析HTML/XML语言并生成文档树。由于其简单易用的特性被许多小型爬虫所采用。

  HTML语言作为一种标记语言,每一个元素都由一对标签包含,层层嵌套形成树状结构。当人去阅读这段代码时,实际内容会被一大串描述元素样式的代码淹没,观察较为繁琐;但程序阅读恰恰相反,标签化、结构化且严谨的语法非常适合程序(浏览器等)理解分析,并按照当初设计的方式渲染重构网页。

  我们获得的来自服务器的响应一般为HTML格式的一个页面,由于HTML语言特性,人类难以直观理解实际效果,这就需要一个程序来解析这个响应。浏览器核心也包含一个HTML解析器,而在爬虫中,Beautiful Soup 4库就起到了这样的效果。

  至于这个Python库的名称为什么是BeautifulSoup4(即bs4)而不是BeautifulSoup,是因为后者已经用来表示BeautifulSoup3库(为了兼容性原因仍然保留),为避免名称冲突,才使用这个名字。

  关于这个库的更多信息以及使用指南,请参阅Beautiful Soup 4官方手册(中文)Beautiful Soup 4.4.0 文档


Beautiful Soup 4库的安装、引用与测试

  • Beautiful Soup 4包安装与安装其他库包的方法相同,Windows cmd/Linux Terminal 下,输入如下命令
pip install beautifulsoup4

等待安装完成即可。

  • 引用这个库的方法与其他库略有不同,实际上,Beautiful Soup 4是一个类,包含在bs4包中,使用时只需要从包中单独引用BeautifulSoup类即可。使用from-import语句实现
from bs4 import BeautifulSoup

注意:BeautifulSoup中的BS为大写字母,Python对大小写敏感

  • 下面使用一个小样例来测试Beautiful Soup 4的功能,该类的基本功能会在下面讲到

示例实现步骤

  1. 使用Requests库下载了一个样例页面
  2. 将响应主体(HTML格式)作为参数声明了一个BeautifulSoup实例soup
  3. 使用其prettify()方法将主体内容进行了优化并输出
import requests
from bs4 import BeautifulSoupr = requests.get("http://python123.io/ws/demo.html")
# 提交请求抓取响应
# print(r.text)
soup = BeautifulSoup(r.text, features="html.parser")
# 声明实例并将响应主体作为参数传入
print(soup.prettify())
#使用prettify()方法输出优化后的内容

BeautifulSoup类使用

 HTML基础知识

在了解BeautifulSoup类的原理前,先来补充一点HTML语言的相关知识。

HTML语言的各个元素均由标签构成,一对一对标签以及中间包括的内容构成了元素,例如:

<p class="title">Hello World</p>

其中,

  • p:标签名称,p表示段落(paragraph)

  • class="title":标签的属性,属性键为class,值为"title",这个属性与CSS样式表相关

  • Hello World:标签主体内容

  • /p:标签结束符号,与p标签开始符号一一对应

  • 标签开始部分(标签名称和属性)与标签结束都由尖括号包含,两个尖括号中间的内容为标签主体内容

这样的标签嵌套叠加,形成了一个树状结构,被称为文档树

HTML文档树

附表:HTML常用标签

标签 名称说明
<a>链接
<b>普通文本
<body>文档主体内容标签
<div>HTML文档中的分隔区块
<form>创建表单用于用户输入
<hn>标题,n为等级1-6
<img>图片
<span>对一部分文本进行着色
<script>JavaScript脚本

 BeautifulSoup类实例化

BeautifulSoup类中的一个实例正与一个文档树一一对应(类本身也是)。**声明一个新的实例时,将HTML内容作为参数传递给实例初始化函数,这个HTML内容所对应的文档树就按照BeautifulSoup类的结构被对应到了实例中。**通过Beautiful Soup库,我们能够对文档树进行解析、遍历、维护。

在初始化一个BeautifulSoup实例时,不仅需要提供HTML文档内容作为参数,还需要选择一个适合的解释器

解析器名称优点缺点
Python标准库解析器html.parser是Python内置标准库 执行速度适中 文档容错能力强较早版本Python中的解析器容错能力弱且不稳定
lxml HTML解析器lxml速度快 文档容错能力强依赖C语言库
lxml XML解析器lxml-xml速度快 唯一一个XML解析器依赖C语言库
html5libhtml5lib容错性最佳 以浏览器方式解析文档 生成html5格式文档速度慢 不依赖外部拓展

其中,Python标准库解析器在Python标准库中,不需要另外安装;其他的解析器需要自行安装第三方库(lxml的两个解析器安装lxml包,html5lib解析器安装html5lib包)

声明一个新实例的语法(尖括号仅表示名称,不在语法中)

<Name> = BeautifulSoup(<HTML Document>, features="<Parser Name>")

其中,

  • Name:新实例的名称
  • HTML Document:需要解析的HTML文档,以字符串形式,也可以为打开的文件
  • Parser Name:解析器名称,各个解析器的名称见上表

 BeautifulSoup类的基本元素

基本元素说明
Tag标签,为文档的最基本组成元素,上面已经介绍
Name标签的名称,例如

标签名称为p,调用格式为<tag>.name
Attributes标签的属性,以字典形式组织,调用格式为<tag>.attrs
NavigableString可以遍历的字符串,为标签内非属性字符串,即为上面提到的标签主体内容,格式<tag>.string
Comment标签内字符串的注释部分,是一种特殊的NavigableString,格式同上
Text标签中的主体内容(不含注释),格式<tag>.text
Beautiful Soup整个文档对应的类的实例,这个元素的名称为[document]
  • 标签元素的类型为bs4.element.Tag
  • 标签的NavigableString不是一个str类型数据,而是Beautiful Soup 4中另行定义的类型bs4.element.NavigableString
  • 关于各种属性的使用方法,请见下面的BeautifulSoup标签的属性

 BeautifulSoup类获取标签

基本元素中,除了Tag为独立的标签元素外,其余所有都可以视作Tag的属性,那么,如何从BeautifulSoup类中提取一个标签呢?我们以实例soup为例

tag_a = soup.a
tag_p = soup.p

实际上,使用soup.就可以获得实例对应文档树中第一个名称为tag name的标签,如果文档树中不存在这个标签,不会报错,而是返回空,且这些标签名称由于不固定,IDE不提供代码补全,所以要小心标签名称错误

注意,使用这个方法只能获得文档中的一个标签,如果需要其他标签,请使用后面讲到的文档遍历

 BeautifulSoup标签的属性

标签的属性在上面的基本元素中已经基本给出,下面挑选必要的属性逐个介绍

  • Attributes:标签属性域中的属性,为字典形式,对于HTML中已经定义的多值属性,将返回一个List(即使只有一个也返回List)
    • 如果该标签没有属性,将返回为空
    • 由于属性为字典格式,可以使用字典的相关操作,例如单独输出某个键的值tag.attrs['class']
  • NavigableString:标签中的主要内容(可遍历字符串),即两对尖括号中间的内容
    • 如果该标签没有可遍历字符串,则返回空
    • 如果不为空,NavigableString不是一个str普通字符串型数据,而是Beautiful Soup 4中另行定义的类型bs4.element.NavigableString
    • 如果一个标签的主体部分既有文本又有注释,则string为空,请见Text
  • Comment:标签中的注释内容,注意:Comment为一种特殊的NavigableString,其使用方法与返回形式完全相同,即使用string,两个返回格式相同,无法从这里区分CommentNavigableString,需要用类型或Text判断
    • 不同于普通的NavigableStringComment有自己独有的类型bs4.element.Comment
    • 如果一个标签的主体部分既有文本又有注释,则string为空,请见Text
  • Text:标签中的主要内容(不包含注释),也是两对尖括号中的内容
    • 与NavigableString不同的是,Text在文本与注释同时出现时,会过滤注释内容,仅保留文本内容
    • Text的类型为str,为Python标准类型

 Beautiful Soup HTML文档遍历方法

Beautiful Soup 支持HTML文档树的上行遍历下行遍历平行遍历三种遍历方法。所有遍历均通过查询当前标签的属性实现,即

<tag>.<attribute>
 下行遍历

从根节点元素开始向文档叶节点遍历(寻找子节点)

Beautiful Soup 为下行遍历提供了三个属性

属性说明
.contents子节点列表,将这个标签的所有子节点(下一层)以列表形式给出
.children子节点的可迭代类型对象,生成这个标签所有子节点(下一层)的可迭代列表对象
.descendants子孙节点的可迭代类型对象,包含这个标签所有子孙节点(下面所有)
  • 注意:子节点不仅有标签类型,也有其他字符串,如\n换行符或纯文本,这些字符串的类型为NavigableString
  • 可迭代类型的原文为list_iterator object
  • .descendants的遍历顺序为先序遍历
 上行遍历

从叶节点元素开始向文档根节点遍历(寻找父节点)

Beautiful Soup 为上行遍历提供了两个属性

属性说明
.parent父节点,这个标签的父节点,仅一个
.parents先辈节点、这个节点的所有父节点的迭代(父节点、父节点的父节点……)
  • 仅在最高一级的根节点[document]节点(参见上文HTML基础知识中文档树结构图)的类型为BeautifulSoup,即为BeautifulSoup本身,其他节点的类型均为bs4.element.Tag
  • 根节点的父节点为空
 平行遍历

在平行节点间横向遍历,平行节点,即兄弟节点,指父节点为同一个节点的一系列节点

Beautiful Soup 为平行遍历提供了四个属性

属性说明
.next_sibling按照HTML文本序的下一个平行节点
.previous_sibling按照HTML文本序的上一个平行节点
.next_siblings按照HTML文本序的下面所有平行节点
.previous_sibling按照HTML文本序的上面所有平行节点
  • 注意:平行节点不仅有标签类型,也有其他字符串,如\n换行符或纯文本等,这些字符串的类型为NavigableString,使用时请注意区分

  • 可以通过判断该元素的name属性是否为None来确定该元素是否为NavigableString(若使用类型判断,则需要导入整个bs4)

    if not tag.name is None:do_something()
    

 Beautiful Soup HTML文档优化

使用Requests库得到的响应文档未经过处理(换行、缩进等),且由于HTML的特性,没有渲染情况下可读性较差,需要通过优化提升可读性,Beautiful Soup类的Prettify()方法提供了这个功能。需要将返回值打印才能看到效果(只是在其中添加换行符)

soup = BeautifulSoup(HTML_text, "html.parser")
print(soup.prettify())

 基于Beautiful Soup库的HTML内容查找方法

  查找标签find_all()

Beautiful Soup提供了一个专用的方法用来查找指定名称的标签

soup.find_all('name')
#soup 为搜索范围的Tag或BeautifulSoup对象,name 为要查找的标签名称

函数返回一个列表,包含所有符合名称的标签

  • 由于列表可遍历(可迭代),可以使用for语句遍历整个搜索结果列表,列表中的元素类型仍然为bs4.element.Tag

  • 当想要获取多个类型的标签时,可以将一个包含有欲查找标签名称(字符串类型)的列表作为参数传入标签

  • 当想要获得这个soup中的所有标签时(相当于树遍历),可以将参数变为True

  • 如果还想要进一步限制查找内容,find_all()函数还提供了class属性参数

    soup.find_all('name', 'attr')
    

    这将搜索所有名称为nameclass类属性为attr的标签
    如果将name设为空'',则将返回所有class符合的标签,而不限制标签名称

  • 还可以限制id属性

    soup.find_all(id = 'link1')
    

    这将搜索所有id属性为"link1"的标签

  • 这个函数的另一个参数recursive递归,默认为True,表示将遍历该标签对象下的所有子孙节点,否则只遍历该节点的子节点

  • 又一个参数string,可以搜索标签主体内容(一对尖括号中间的内容),返回类型为NagivableString

    必须精确匹配内容才能搜索到,实际没有太大意义,以后将使用正则表达式标准库re来完成正则表达式匹配搜索

 其他查找语句

除了find_all()外,Beautiful Soup还提供了其他特性的搜索函数,这些函数的参数与find_all()相同,有对应需求时,直接使用函数即可

函数说明
.find()搜索且只返回第一个结果
.find_parents()在先辈节点中搜索,返回列表
.find_parent()在先辈节点中搜索,且只返回一个结果
.find_next_siblings()在后续平行节点中搜索,返回一个列表
.find_next_sibling()在后续平行节点中搜索,且只返回一个结果
.find_previous_siblings()在之前的平行节点中搜索,返回一个列表
.find_previous_sibling()在之前的平行节点中搜索,且只返回一个结果

这篇关于Python 网络爬虫从0到1 (4):Beautiful Soup 4库入门详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/510294

相关文章

Java Spring的依赖注入理解及@Autowired用法示例详解

《JavaSpring的依赖注入理解及@Autowired用法示例详解》文章介绍了Spring依赖注入(DI)的概念、三种实现方式(构造器、Setter、字段注入),区分了@Autowired(注入... 目录一、什么是依赖注入(DI)?1. 定义2. 举个例子二、依赖注入的几种方式1. 构造器注入(Con

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

mybatis中resultMap的association及collectio的使用详解

《mybatis中resultMap的association及collectio的使用详解》MyBatis的resultMap定义数据库结果到Java对象的映射规则,包含id、type等属性,子元素需... 目录1.reusltmap的说明2.association的使用3.collection的使用4.总

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

Apache Ignite缓存基本操作实例详解

《ApacheIgnite缓存基本操作实例详解》文章介绍了ApacheIgnite中IgniteCache的基本操作,涵盖缓存获取、动态创建、销毁、原子及条件更新、异步执行,强调线程池注意事项,避免... 目录一、获取缓存实例(Getting an Instance of a Cache)示例代码:二、动态

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法

《Python错误AttributeError:NoneTypeobjecthasnoattribute问题的彻底解决方法》在Python项目开发和调试过程中,经常会碰到这样一个异常信息... 目录问题背景与概述错误解读:AttributeError: 'NoneType' object has no at