爬虫时如何利用BeautifulSoup获取我们需要的数据?

2023-11-02

爬虫大致可以分为三步:

  • 第一步,发送request请求获得html内容
  • 第二步,清洗数据,即从html原网页数据中筛选我们需要的数据
  • 第三步,将需要的数据储存
    在第二步筛选数据是,我们往往可以利用BeautifulSoup来完成,下面就如何利用BeautifulSoup来解析原html网页数据并获取我们需要的内容进行讲解。

1 认识HMTL的结构 – 预备知识

html中有两个很重要的概念就是标签属性,可以说html就是有一个一个的标签和标签之间的内容构成的,标签位于<>之后,通常都是成对出现。
详细内容参可以参考:菜鸟教程html

1.1 标签

标签位于<>之中,一般都是成对出现,格式如下:
<标签>内容</标签>

直接上上一段html代码,所有红色字体部分都是标签:

<!DOCTYPE html>
<html>
<head>
	<title>The Dormouse's story</title>
</head>
<body>
	<!-- a href="http://example.com/elsie" class="sister" id="link0">link0</a -->
	<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
	<p>一个图像:<img src="smiley.gif" alt="Smiley face" width="32" height="32"></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">this a new story</p>
</body>
</html>

代码中,所有红色字体的都是标签,比如、

,并且标签都是成对出现, 起始标签和结束标签之间的白色字体部分(可能嵌套了其他标签)就是文本内容。这段html的显示效果如下:
在这里插入图片描述

1.2 属性

属性,就是用来描述标签的一些特性,比如 < a>标签代表是链接,href属性就是给定了这个标签链接的具体地址。再比如,标签代表图像,src代表了图片的路径,width和height属性分别指定了图片的宽度和高度。属性位于起始所在的<>中,并且跟在起始标签的后面,格式如下:
<标签 属性名1= 属性值1 属性名2 = 属性值2>内容</标签>
上面html代码中,橘黄色部分就是属性名,绿色部分就是对应的属性值,中间用=连接

1.3 文本内容与标签内容

这两个概念可能并不准确,只是为了方便后续描述。因为使用BeautifulSoup方法时,返回的内容基本上都是标签内容文本内容
这简单来说,起始标签和结束标签之间的所有部分(包含起始标签和结束标签)就是这个标签对应的标签内容。而文本内容就是位于起始标签和结束标签之间<>之外的的部分。这句话感觉有点奇怪,该怎么理解呢?
举个例子:

<title>The Dormouse's story</title>

对于title来说,标签内容是:<title>The Dormouse's story</title>
文本内容就是:The Dormouse's story

<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

对于标签p来说,文本内容就是:The Dormouse’s story,因为中间嵌套了另外一个标签b,但是内容是不算b的,因为b属于标签,位于<>之中。当然也可以说标签b的文本内容是:The Dormouse’s story。这个标签的标签内容就是:<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

为上面要强调这个概念呢?因为爬虫很多时候都是需要获取文本内容,BeautifulSoup很多方法返回的就是标签内容标签内容组成的列表,标签内容进一步通过**.string或者.text就可以得到文本内容**。

2 初识BeautifuSoup

2.1 BeautifulSoup四大对象

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

  • Tag, 标签,即对应html中的标签
  • NavigableString,遍历字符串,即对应html中的内容
  • BeautifulSoup,soup对象,可以看作是一个特殊的tag,代表文档的全部内容
  • Comment,可以看作是特殊的NavigableString,代表文档中注释的字符串

由于BeautifulSoup将html文档转化成立包含四种对象的复杂树形结构,因此,可以利用着四种对象来获取html中不同的内容。

2.2 .tag获取一个标签内容

< 标签>起止标签以及这部分就是标签内容< /标签>, 很多时候我们需要先提取两个标签之间的那部分内容,为了方便叙述,成为标签内容。注意,这部分内容可能还嵌套了其它的标签。
假如我们已经构造了一个BeautifulSoup对象soup,那么就可以利用soup.tag的方式获取标签对应的那部分内容,注意这个内容是包含标签本身的。
废话少说,直接上python代码演示:

import requests
from bs4 import BeautifulSoup
html = """
<html>
<head>
	<title>The Dormouse's story</title>
</head>
<body>
	<!-- a href="http://example.com/elsie" class="sister" id="link0">link0</a -->
	<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
	<p>一个图像:<img src="smiley.gif" alt="Smiley face" width="32" height="32"></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">this is a new story</p>
</body>
</html>
"""

soup = BeautifulSoup(html, 'xml')
print(soup.head)
print(soup.p)
print(soup.b)

显示结果如下:
在这里插入图片描述
对比原来的html代码可以知道,soup.tag可以提取html中tag对应的那部分内容,并且保留了原来的格式。需要注意的是,如果html中有多个相同的标签,soup.tag只能提取里面的第一个标签对应的内容
比如原html中有多个p标签,soup.p只是提取了第一个p标签代表的内容。如果要获取每个标签对应内容怎么办呢?可以使用find_all()函数,后面再讲。
从html代码我们可以知道,第一个p标签对应的内容如下:

<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

我们还可以进一步提取里里面的属性值,方法如下:
soup.tag[属性名]:

print(soup.p['class'])
print(soup.p['name'])

上面两行代码显示如下:
title
dromouse
当然也可以用get函数来获取属性值
soup.p.get(‘name’) 与 soup.p[‘name’] 效果是一样的。

另外需要说明的时,如果利用soup.tag获取某个标签内容,还可以对里面的标签内容进行遍历:
假如获取了某个个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标签内容余下按部分按照嵌套的标签内容文本内容可以分为7个部分:

<p class="story">【1 Once upon a time there were three little sisters; and their names were】
		【2 <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>】【3 ,】
		【4 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>】 【5 and】
		【6 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>】【7 ;
		and they lived at the bottom of a well.】
	</p>

划分的依据就是,如果是新的标签或文本就是一个单独的元素。这样我们可以通过遍历的方式得到里面的每一个元素:

# 假如已经通过BeautifulSoup获取上面p标签内容tag_pContent,就可以遍历里面的7个元素了
for t in tag_pContent:
	print(t)

2.3 .string或.text获取标签中间的文本内容

前面专门强调了文本内容这个概念,因为很多时候我们就是要获取标签之外的文本内容。
利用2.2中方法获取了标签内容之后,要获取文本内容就很简单了,因为文本内容包含在起始标签与结束标签之间。方法:
soup.tag.stringsoup.tag.text, 其中,soup.tag获取了标签内容,再加上**.string.text**就可以获取里面的文本内容了。
接着上面的例子:
print(soup.p.string) 或print(soup.p.text)就会显示如下:
The Dormouse’s story

2.4 BeautifulSoup可以看作是特殊的tag

BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称,以及属性来感受一下:

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

2.5 Comment

Comment 对象是一个特殊类型的 NavigableString 对象,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。
加入soup.a对应的内容如下:

<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>

那么soup.a.string输出如下:
Elsie
实际上,Elsie是注释内容!,因此Comment可以看作是特殊的NavigableString对象。但是和类型不同,soup.a.string的类型为<class ‘bs4.element.Comment’>,因此为了造成意想不到的麻烦,可以用如下判断进行区分:

if type(soup.a.string)==bs4.element.Comment:
  print("这是注释")

3 BeautifulSoup常用的一些函数或属性

3.1 find以及find_all函数返回标签内容

BeafutifulSoup中有很多函数,但是这个两个函数几乎是用得最多的,所以重点讲一下。find和find_all这两个函数和soup.tag获取的内容的形式都是一样,都是获取标签内容
先看下函数原型吧:

find_all( tag_name , attrs , recursive , text , **kwargs ) # 返回列表
find( tag_name , attrs , recursive , text , **kwargs ) # 返回一找到的一个元素

这个两个函数区别就是,find只会返回满足条件的第一个标签内容,而find_all会将所有满足条件的标签内容以列表的形式返回。当find函数只使用第一个参数tag_name时,和soup.tag_name的效果时一样的。
比如:
soup.p和soup.find(‘p’)的结果是一样的。
比如对于下面这3个p标签,如何得到最后一个标签内容呢?可以利用标签属性进行过滤,第三个p标签具有class=’story‘的属性,但是前两个没有。
于时:
soup.find(‘p’, class_ =‘story’)

<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p>一个图像:<img src="smiley.gif" alt="Smiley face" width="32" height="32"></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>	
print(soup.find('p'))
# 特别需要注意,由于class是python内置关键字,这里参数中需要用class_代替class
print(soup.find('p', class_='story'))

上面两行代码代码打印如下:
在这里插入图片描述
特别需要注意,由于class是python内置关键字,这里参数中需要用class_代替class

3.2 .strings 或.stripped_strings 属性获取所有的文本内容

.strings可以获取所有的文本内容组成的列表(需要通过遍历来访问),但是这个包含了一些原来文本中的一些空白字符,而.stripper_strings可以也是获取所有的文本内容,但是去掉了很多空格或空行。

soup = BeautifulSoup(html, 'xml')
for text in soup.strings:   # 遍历所有的文本内容
	print(text)

输出结果如下:
在这里插入图片描述

soup = BeautifulSoup(html, 'xml')
for text in soup.stripped_strings:   # 遍历所有的文本内容
	print(text)

在这里插入图片描述

【参考文章】
1、Python中使用Beautiful Soup库的超详细教程

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

爬虫时如何利用BeautifulSoup获取我们需要的数据? 的相关文章

  • @media语法/可能的组合

    我见过其中一些 media print media screen handheld print projection media all media all and property value media screen and prope
  • 使用 on_bad_lines 将 pandas.read_csv 中的无效行写入文件

    我有一个 CSV 文件 我正在使用 Python 来解析该文件 我发现文件中的某些行具有不同的列数 001 Snow Jon 19801201 002 Crom Jake 19920103 003 Wise Frank 19880303 l
  • 图像无法在带有 DOM 的 IE 中加载:控制台中的 7009 错误(无法解码)

    当在 IE 中的单个页面上加载许多图像时 在 IE11 中重现 其中一些图像开始加载失败 并在控制台中出现类似以下警告的内容 DOM7009 无法解码 URL 处的图像 某些唯一的 url 当我查看网络流量时 似乎确实从服务器收到了每个图像
  • Python 函数可以从作用域之外赋予新属性吗?

    我不知道你可以这样做 def tom print tom s locals locals def dick z print z name z name z guest Harry print z guest z guest print di
  • 如何使用 OpencV 从 Firebase 读取图像?

    有没有使用 OpenCV 从 Firebase 读取图像的想法 或者我必须先下载图片 然后从本地文件夹执行 cv imread 功能 有什么办法我可以使用cv imread link of picture from firebase 您可以
  • 从 Flask 访问 Heroku 变量

    我已经使用以下命令在 Heroku 配置中设置了数据库变量 heroku config add server xxx xxx xxx xxx heroku config add user userName heroku config add
  • 如何在Python中获取葡萄牙语字符?

    我正在研究葡萄牙语 角色看起来很奇怪 我怎样才能解决这个问题 代码 import feedparser import random Vou definir os feeds feeds conf feedurl http pplware s
  • 添加不同形状的 numpy 数组

    我想添加两个不同形状的 numpy 数组 但不进行广播 而是将 缺失 值视为零 可能最简单的例子是 1 2 3 2 gt 3 2 3 or 1 2 3 2 1 gt 3 2 3 1 0 0 我事先不知道形状 我正在弄乱每个 np shape
  • Flask如何获取请求的HTTP_ORIGIN

    我想用我自己设置的 Access Control Allow Origin 标头做出响应 而弄清楚请求中的 HTTP ORIGIN 参数在哪里似乎很混乱 我在用着烧瓶 0 10 1 以及HTTP ORIGIN似乎是这个的特点之一object
  • 如何在Python中对类别进行加权随机抽样

    给定一个元组列表 其中每个元组都包含一个概率和一个项目 我想根据其概率对项目进行采样 例如 给出列表 3 a 4 b 3 c 我想在 40 的时间内对 b 进行采样 在 python 中执行此操作的规范方法是什么 我查看了 random 模
  • 刷新页面时保存用户的选择

    我目前有一个页面显示不同团队的数据 我有一些数据 用户可以单击使其处于 打开 或 关闭 状态 并为每个数据显示不同的图标 它基本上就像一个清单 只是没有物理复选框 我想记住哪些 复选框 已被选中 即使在用户刷新页面或关闭浏览器并稍后返回之后
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i
  • 图像背景不透明度不影响边框

    如何设置背景不透明度而不影响边框线不透明度 我找到的解决方案没有帮助 div class selected img src assets img image product 1 thumbnail jpg alt product 1 thu
  • 类型错误:预期单个张量时的张量列表 - 将 const 与 tf.random_normal 一起使用时

    我有以下 TensorFlow 代码 tf constant tf random normal time step batch size 1 1 我正进入 状态TypeError List of Tensors when single Te
  • Conda SafetyError:文件大小不正确

    使用创建 Conda 环境时conda create n env name python 3 6 我收到以下警告 Preparing transaction done Verifying transaction SafetyError Th
  • Python:如何将列表列表的元素转换为无向图?

    我有一个程序 可以检索 PubMed 出版物列表 并希望构建一个共同作者图 这意味着对于每篇文章 我想将每个作者 如果尚未存在 添加为顶点 并添加无向边 或增加每个合著者之间的权重 我设法编写了第一个程序 该程序检索每个出版物的作者列表 并
  • Scrapy:如何使用元在方法之间传递项目

    我是 scrapy 和 python 的新手 我试图将 parse quotes 中的项目 item author 传递给下一个解析方法 parse bio 我尝试了 request meta 和 response meta 方法 如 sc
  • 在 Qt 中自动调整标签文本大小 - 奇怪的行为

    在 Qt 中 我有一个复合小部件 它由排列在 QBoxLayouts 内的多个 QLabels 组成 当小部件调整大小时 我希望标签文本缩放以填充标签区域 并且我已经在 resizeEvent 中实现了文本大小的调整 这可行 但似乎发生了某
  • 导入错误:没有名为 site 的模块 - mac

    我已经有这个问题几个月了 每次我想获取一个新的 python 包并使用它时 我都会在终端中收到此错误 ImportError No module named site 我不知道为什么会出现这个错误 实际上 我无法使用任何新软件包 因为每次我
  • 如何将输入读取为数字?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 Why are x and y下面的代码中使用字符串而不是整数 注意 在Python 2

随机推荐

  • (一)K8S集群部署——master节点部署

    1 集群配置 本次部署使用三台服务器 master 192 168 0 2 node1 192 168 0 4 node2 192 168 0 14 服务器配置均为 CentOS 7 6 64位 8核 16G 100G 2 master部署
  • Unity 3D 读入本地 xml 文件

    Load and Display XML Data in Unity 3D 如果你能翻墙从 youtube 上就可以看到怎么用 using UnityEngine using System Collections
  • IDM怎么设置下载会更快

    虽然IDM的下载速度已经足够彪悍 其优秀的智能动态文件分段功能和安全的分段下载技术 让大多数下载器都望尘莫及 但贪心的我们总是希望下载速度能更快 实际上 IDM也隐藏了部分功力 并可通过配置设置将隐藏的 功力 发挥出来 一般来说 Inter
  • 基于MFC对话框的Windows服务程序

    最近需求要写个服务程序 部分功能用MFC类库实现将非常方便 因此就没打算使用win32的服务程序 虽然那样对于服务很简单 首先写好mfc的对话框程序 调试什么的 功能也都完成好 这一部分和平常的mfc对话框程序没有差别 之后的服务启动后打开
  • Elasticsearch--索引备份与迁移

    Elasticsearch集群备份 以及在不同集群之间迁移数据 类似mongodb的mongodump功能 Elasticsearch也提供了备份集群中索引数据的策略 snapshot API 它会备份整个集群的当前状态和数据 并保存到集群
  • java操作rabbitmq

    JMS JMS是JavaEE规范中的一种 类比JDBC JMS即Java消息服务 JavaMessage Service 应用程序接口 是一个Java平台中关于面向消息中间件的API很多MQ产 品都实现了JMS规范 但RabbitMQ官方并
  • Rsync的配置与使用

    一 介绍 不想看直接可以跳过 Rsync 是一个远程数据同步工具 可通过 LAN WAN 快速同步多台主机间的文件 Rsync 本来是用以取代rcp 的一个工具 它当前由 rsync samba org 维护 Rsync 使用所谓的 Rsy
  • [Transformer]CSWin Transformer: A General Vision Transformer Backbone with Cross-Shaped Windows

    CSWin Transformer 基于交叉十字形窗口的视觉Transformer框架 Abstract Section I Introduction Section II Related Work Section III Method P
  • 使用数字滤波器处理音频噪声(附Matlab程序)

    本篇文章主要介绍使用窗函数法构造FIR数字滤波器 并且滤除音频文件的噪声 以下为完整的程序 修改一下文件的位置 直接复制应该就可以 1 音频文件的采集与分析 Matlab输入的音频文件需要 wav 文件 可以使用一些软件转换格式 例如酷狗音
  • C#音频采集 (笔记)

    using System using System Collections Generic using System Text using System IO using System Threading using Microsoft D
  • Effective C++第七章-模板和泛型编程之模板特化和代码膨胀

    模板特化 class A public void func1 void func2 class B public void func1 void func2 template
  • 用JS的canvas实现数字签名

    用JS的canvas实现数字签名 思路 先创建画布 鼠标按下 同时随着鼠标的移动来绘制签名 最后鼠标松开绘制结束 直接上代码啦
  • electron 1. hello world

    cnpm init y cnpm i electron D 安装electron package json name news windows version 1 0 0 description main main js scripts t
  • 爬取电影天堂

    电影天堂爬虫之网页分析 from lxml import etree import requests BASE DOMAIN http www ygdy8 net url http www ygdy8 net html gndy dyzz
  • java中的sleep()和wait()的区别

    对于sleep 方法 我们首先要知道该方法是属于Thread类中的 而wait 方法 则是属于Object类中的 sleep 方法导致了程序暂停执行指定的时间 让出cpu该其他线程 但是他的监控状态依然保持者 当指定的时间到了又会自动恢复运
  • Java中的桥接模式(Bridge Pattern)

    Java中的桥接模式 Bridge Pattern Java中的桥接模式 Bridge Pattern 是一种结构性设计模式 它将抽象部分和实现部分分离 使它们可以独立变化 同时通过桥接对象将它们连接起来 桥接模式通过将继承关系转变为对象组
  • 简单了解Docker、Dubbo

    简单了解Docker Dubbo 以Docker为例的容器 Docker是什么 Docker的原理 以Dubbo为例的RPC调用框架 如何理解REST RPC Dubbo是什么 简单了解Docker Dubbo 以Docker为例的容器 D
  • 分号和逗号

    分号是语句的结束字符 逗号是声明变量时分割符 分号一般表示语句的终结 或者用来分隔for语句中的3段 逗号一般用来分隔先后两条子句 或在函数定义或调用中分隔参数 如 var i 0 j 2 for var k 0 k lt j k i i
  • 【华为OD机试真题】密室逃生游戏(python)100%通过率 超详细代码注释 代码优化

    华为OD机试真题 2022 2023 真题目录 点这里 华为OD机试真题 信号发射和接收 试读 点这里 华为OD机试真题 租车骑绿道 试读 点这里 密室逃生游戏 题目描述 小强正在参加 密室逃生 游戏 当前关卡要求找到符合给定 密码 K 升
  • 爬虫时如何利用BeautifulSoup获取我们需要的数据?

    爬虫大致可以分为三步 第一步 发送request请求获得html内容 第二步 清洗数据 即从html原网页数据中筛选我们需要的数据 第三步 将需要的数据储存 在第二步筛选数据是 我们往往可以利用BeautifulSoup来完成 下面就如何利