python爬虫--beautifulsoup模块简介

news2025/1/11 14:48:31

BeautifulSoup 的引入

我们学习了正则表达式的相关用法,但是一旦正则写的有问题,可能得到的就不是我们想要的结果了,而且对于一个网页来说,都有一定的特殊的结构和层级关系,而且很多标签都有 id 或 class 来对作区分,所以我们借助于它们的结构和属性来提取不也是可以的吗?

所以,这一节我们就介绍一个强大的解析工具,叫做 BeautiSoup,它就是借助网页的结构和属性等特性来解析网页的工具,有了它我们不用再去写一些复杂的正则,只需要简单的几条语句就可以完成网页中某个元素的提取。

废话不多说,接下来我们就来感受一下 BeautifulSoup 的强大之处吧。

BeautifulSoup 简介

简单来说,BeautifulSoup 就是 Python 的一个 HTML 或 XML 的解析库,我们可以用它来方便地从网页中提取数据,官方的解释如下:

BeautifulSoup 提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。BeautifulSoup 自动将输入文档转换为 Unicode 编码,输出文档转换为 utf-8 编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时你仅仅需要说明一下原始编码方式就可以了。BeautifulSoup 已成为和 lxml、html6lib 一样出色的 python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。

所以说,利用它我们可以省去很多繁琐的提取工作,提高解析效率。

BeautifulSoup 的安装

使用之前,我们当然需要首先说明一下它的安装方式。目前 BeautifulSoup 的最新版本是 4.x 版本,之前的版本已经停止开发了,推荐使用 pip 来安装,安装命令如下:

pip install beautifulsoup4

好,安装完成之后可以验证一下,写一段 Python 程序试验一下。

from bs4 import BeautifulSoup
soup = BeautifulSoup('<p>Hello</p>', 'html.parser')print(soup.p.string)

运行结果

Hello

如果没有报错,则证明安装没有问题。

解析器:

BeautifulSoup 在解析的时候实际上是依赖于解析器的,它除了支持 Python 标准库中的 HTML 解析器,还支持一些第三方的解析器比如 lxml,下面我们对 BeautifulSoup 支持的解析器及它们的一些优缺点做一个简单的对比。

解析器使用方法优势劣势 

Python 标准库 BeautifulSoup (markup, "html.parser") Python 的内置标准库、执行速度适中 、文档容错能力强 Python 2.7.3 or 3.2.2) 前的版本中文容错能力差 

lxml HTML 解析器 BeautifulSoup (markup, "lxml") 速度快、文档容错能力强需要安装 C 语言库 

lxml XML 解析器 BeautifulSoup (markup, "xml") 速度快、唯一支持 XML 的解析器需要安装 C 语言库 

html5libBeautifulSoup (markup, "html5lib") 最好的容错性、以浏览器的方式解析文档、生成 HTML5 格式的文档速度慢、不依赖外部扩展 

所以通过以上对比可以看出,lxml 这个解析器有解析 HTML 和 XML 的功能,而且速度快,容错能力强,所以推荐使用这个库来进行解析,但是这里的劣势是必须安装一个 C 语言库,它叫做 lxml,我们在这里依然使用 pip 安装即可,命令如下:

pip3 install lxml

安装完成之后,我们就可以使用 lxml 这个解析器来解析了,在初始化的时候我们可以把第二个参数改为 lxml,如下:

from bs4 import BeautifulSoup
soup = BeautifulSoup('<p>Hello</p>', 'lxml')
print(soup.p.string)

运行结果是完全一致的。

基本使用:

下面我们首先用一个实例来感受一下 BeautifulSoup 的基本使用:

html = """<html><head><title>The Dormouse's story</title></head><body><p class="title" name="dromouse"><b>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>"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml') # lxml写成html.parser也可以,同样的效果,都是解析器
print(soup.prettify())
print("#"*30)
print(soup.title.string)

运行结果

<html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <p class="title" name="dromouse">
   <b>
    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 :="" class="sister" elsie"="" example.com="" id="link1">
    <!-- Elsie -->
    ,
    <a href="http: class="sister" example.com="" id="link2" lacie"="">
     Lacie
     and
     <a href="http: class="sister" example.com="" id="link3" tillie"="">
      Tillie
      ;and they lived at the 
bottom of a well.
      <p class="story">
       ...
      </p class="story">
     </a href="http:>
    </a href="http:>
   </a href="http>
  </p class="story">
 </body>
</html>
##############################
The Dormouse's story

首先我们声明了一个变量 html,它是一个 HTML 字符串,但是注意到,它并不是一个完整的 HTML 字符串,<body> 和 <html> 标签都没有闭合,但是我们将它当作第一个参数传给 BeautifulSoup 对象,第二个参数传入的是解析器的类型,在这里我们使用 lxml,这样就完成了 BeaufulSoup 对象的初始化,将它赋值给 soup 这个变量。

那么接下来我们就可以通过调用 soup 的各个方法和属性对这串 HTML 代码解析了。

我们首先调用了 prettify () 方法,这个方法可以把要解析的字符串以标准的缩进格式输出,在这里注意到输出结果里面包含了 </body> 和 </html> 标签,也就是说对于不标准的 HTML 字符串 BeautifulSoup 可以自动更正格式,这一步实际上不是由 prettify () 方法做的,这个更正实际上在初始化 BeautifulSoup 时就完成了。

然后我们调用了 soup.title.string,这个实际上是输出了 HTML 中 <title> 标签的文本内容。所以 soup.title 就可以选择出 HTML 中的 <title> 标签,再调用 string 属性就可以得到里面的文本了,所以我们就可以通过简单地调用几个属性就可以完成文本的提取了,是不是非常方便?

标签选择器:

刚才我们选择元素的时候直接通过调用标签的名称就可以选择节点元素了,然后再调用 string 属性就可以得到标签内的文本了,这种选择方式速度非常快,如果单个标签结构话层次非常清晰,可以选用这种方式来解析。

选择元素

下面我们再用一个例子详细说明一下它的选择方法。

html = """<html><head><title>The Dormouse's story</title></head><body><p class="title" name="dromouse"><b>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>"""
 from bs4 import BeautifulSoup
 soup = BeautifulSoup(html, 'lxml')
 print(soup.title)
 print(type(soup.title))
 print(soup.title.string)
 print(soup.head)
 print(soup.p)

运行结果

<title>The Dormouse's story</title>
<class 'bs4.element.Tag'>
The Dormouse's story
<head><title>The Dormouse's story</title></head>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

在这里我们依然选用了刚才的 HTML 代码,我们首先打印输出了 title 标签的选择结果,输出结果正是 title 标签加里面的文字内容。接下来输出了它的类型,是 bs4.element.Tag 类型,这是 BeautifulSoup 中的一个重要的数据结构,经过选择器选择之后,选择结果都是这种 Tag 类型,它具有一些属性比如 string 属性,调用 Tag 的 string 属性,就可以得到节点的文本内容了,所以接下来的输出结果正是节点的文本内容。

接下来我们又尝试选择了 head 标签,结果也是标签加其内部的所有内容,再接下来选择了 p 标签,不过这次情况比较特殊,我们发现结果是第一个 p 标签的内容,后面的几个 p 标签并没有选择到,也就是说,当有多个标签时,这种选择方式只会选择到第一个匹配的标签,其他的后面的标签都会忽略。

提取信息:

在上面我们演示了调用 string 属性来获取文本的值,那我们要获取标签属性值怎么办呢?获取标签名怎么办呢?下面我们来统一梳理一下信息的提取方式

获取名称:

可以利用 name 属性来获取标签的名称。还是以上面的文本为例,我们选取 title 标签,然后调用 name 属性就可以得到标签名称。

print(soup.title.name)

运行结果

title

属性获取:

每个标签可能有多个属性,比如 id,class 等等,我们选择到这个节点元素之后,可以调用 attrs 获取所有属性。

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

运行结果

{'class': ['title'], 'name': 'dromouse'}
dromouse

 BeautifulSoup 案例

基本流程:

# 创建BeautifulSoup对象
from bs4 import BeautifulSoup
# 根据HTML网页字符创建BeautifulSoup对象

soup=BeautifulSoup(
    "html_doc",   # HTML文档字符串
    "html.parser",   # HTML解析器
    from_encoding="utf-8"   # HTML文档的编码
)
# 搜索节点(find_all,find)
# 方法:find_all(name,attrs,string)
# 查找所有标签为a的节点
soup.find_all("a")
# 查找所有标签为a,链接符合/view/123.htm形式的节点
soup.find_all("a",href="/view/123.htm")
# 查找所有标签为div,class为abc,文字为Python的节点
soup.find_all("div",class_="abc",string="Python")

获取疯狂的蚂蚁网站首页的文章:

url="http://www.crazyant.net"
import requests
r=requests.get(url)
if r.status_code!=200:
    raise Exception
html_doc=r.text
from bs4 import BeautifulSoup
soup=BeautifulSoup(html_doc,"html.parser")
h2_nodes=soup.find_all("h2",class_="entry-title")
for h2_node in h2_nodes:
    link=h2_node.find("a")
    print(link["href"],link.get_text())

 爬取三国演义小说所有文章:

from bs4 import BeautifulSoup
import requests
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'}
url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(url=url,headers=headers).content.decode("utf-8")
soup = BeautifulSoup(page_text,'html.parser')
li_list = soup.select('.book-mulu > ul > li')
fp = open('./三国演义小说.txt','w',encoding='utf-8')

for li in li_list:
    title = li.a.string
    detail_url = 'https://www.shicimingju.com'+li.a['href']
    detail_page_text = requests.get(url=detail_url,headers=headers).content.decode("utf-8")
    detail_soup = BeautifulSoup(detail_page_text, 'html.parser')
    div_tag = detail_soup.find('div',class_='chapter_content')
    content = div_tag.text
    fp.write('\n' + title + ':' + content +'\n')
    print(title,'爬取成功')

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3+node.js实现webScoket双向通信

Vue3 webScoket方法封装 Node.js webScoket 方法封装 1.先实现服务端node.js scoket方法的封装 先安装ws(基于node.js开发的webScoket 库) npm install ws 2.新建一个webScoket.js文件 3.代码逻辑实现 const Scoket require(ws) // 当前scoket对象 let scoket {} //当前…

C++STL剖析(四)—— stack和queue的概念和使用

文章目录1. stack的介绍2. stack的构造3. stack的使用&#x1f351; push&#x1f351; top&#x1f351; pop&#x1f351; empty&#x1f351; size&#x1f351; swap&#x1f351; emplace4. queue的介绍5. queue的构造6. queue的使用&#x1f351; push&#x1f351; size…

面试官:String、StringBuffer、StringBuilder有什么区别?

回答思路&#xff1a; 阐述String概念理解 存在问题和设计考量 总结体现的两个特性 StringBuilder/StringBuffer相同点和不同点 三者使用场景总结 回答总结&#xff1a; String是Java中非常常见且基础的类&#xff0c;用于字符串的构造和管理&#xff0c;它是Immutable类的经典…

SpringCloud之断路器聚合监控

一、Hystrix Turbine简介 看单个的Hystrix Dashboard的数据并没有什么多大的价值&#xff0c;要想看这个系统的Hystrix Dashboard数据就需要用到Hystrix Turbine。Hystrix Turbine将每个服务Hystrix Dashboard数据进行了整合。Hystrix Turbine的使用非常简单&#xff0c;只需要…

APP 怎么免费接入 MobPush

1、获取 AppKey 申请 Appkey 的流程&#xff0c;请点击 http://bbs.mob.com/thread-8212-1-1.html?fromuid70819 2、下载 SDK 下载解压后&#xff0c;如下图&#xff1a; 目录结构 &#xff08;1&#xff09;Sample&#xff1a;演示Demo。&#xff08;2&#xff09;SDK&am…

干货 | 什么是磁传感器?最常用的磁传感器类型及应用

1、什么是磁传感器&#xff1f;磁传感器通常是指将磁场的大小和变化转换成电信号。磁场&#xff0c;以地球磁场(地磁)或磁石为例的磁场是我们熟悉但不可见的现象。将不可见的磁场转化为电信号&#xff0c;以及转化为可见效应的磁传感器一直以来都是研究的主题。从几十年前使用电…

2/9考试总结

时间安排 7:30–7:50 读题&#xff0c;T1貌似需要建图&#xff0c;T2 dp &#xff0c;T3 神秘博弈。 7:50–8:40 T1&#xff0c;首先可以建图&#xff0c;然后可以发现许多优秀性质&#xff0c;发现题目要求实际上是在每棵树上选一条价值最大的链。问题在于如何取最大&#xf…

MySQL事务管理

文章目录MySQL事务管理事务的概念事务的版本支持事务的提交方式事务的相关演示事务的隔离级别查看与设置隔离级别读未提交&#xff08;Read Uncommitted&#xff09;读提交&#xff08;Read Committed&#xff09;可重复读&#xff08;Repeatable Read&#xff09;串行化&#…

2023开工开学火热!远行的人们,把淘特箱包送上顶流

春暖花开&#xff0c;被疫情偷走的三年在今年开学季找补回来了。多个数据反馈&#xff0c;居民消费意愿大幅提升。在淘特上&#xff0c;开工开学节点就很是明显&#xff1a;1月30日以来&#xff0c;淘特箱包品类甚至远超2022年双11&#xff0c;成为开年“第一爆品”。与此同时&…

第四章第七节:CNN练习1使用四种网络结构(VGG、ResNet、MobileNet、InceptionNet)进行cifar10训练

文章目录一&#xff1a;cifar10数据集介绍二&#xff1a;代码&#xff08;1&#xff09;数据加载脚本编写&#xff08;2&#xff09;模型搭建①&#xff1a;VGG②&#xff1a;ResNet③&#xff1a;MobileNetV1④&#xff1a;InceptionNet&#xff08;3&#xff09;训练脚本一&a…

存储式示波器如何保存图片?

示波器是检测电子线路最有效的工具之一&#xff0c;通过观察电子电路中一些关键节点如某些引脚&#xff0c;MOS管的输出波形&#xff0c;可以直观的检查电路工作是否正常&#xff0c;验证电子电路设计是否恰当。在平时使用示波器的过程中&#xff0c;经常会用示波器去卡某一个信…

canvas 制作2048

效果展示 对UI不满意可以自行调整&#xff0c;这里只是说一下游戏的逻辑&#xff0c;具体的API调用不做过多展示。 玩法分析 2048 的玩法非常简单&#xff0c;通过键盘的按下&#xff0c;所有的数字都向着同一个方向移动&#xff0c;如果出现两个相同的数字&#xff0c;就将…

docker安装elashticsearch

福利&#xff1a;这是我的个人IT资源网站&#xff0c;所有资源都免费&#xff0c;注册登录后就可以看到密码&#xff0c;需要什么大家尽情选取&#xff01; 从docker下载elashticsearch镜像&#xff08;可以指定版本号&#xff09; docker pull elasticsearch:7.4.22. 从dock…

网络安全实验室3.脚本关

3.脚本关 1.key又又找不到了 url&#xff1a;http://lab1.xseclab.com/xss1_30ac8668cd453e7e387c76b132b140bb/index.php 点击链接&#xff0c;burp抓包&#xff0c;发送到重放模块&#xff0c;点击go 得到key is : yougotit_script_now 2.快速口算 url&#xff1a;http:…

树莓派开机自启动Python脚本或者应用程序

树莓派开机自启动Python脚本或者应用程序前言一、对于Python脚本的自启动方法1、打开etc/rc.local文件2、编辑输入需要启动的指令3、重启树莓派验证二、对于需要读写配置文件的应用程序的自启前言 在树莓派上写了一些Python脚本&#xff0c;还有一个java 的jar包想要在树莓派上…

2023年,什么样的CRM,才是您最需要的?

春节假期刚刚结束&#xff0c;当大家还沉浸在新春佳节的喜悦中时&#xff0c;很多地方已经争先恐后地奋力开跑了。近日&#xff0c;全国各地方政府相继出台并发布了2023年数字化转型规划&#xff0c;纷纷结合自身的区位特色和优势资源&#xff0c;明确2023年乃至此后数年的数字…

动态规划详解(完结篇)——如何抽象出动态规划算法?以及解题思路

今天直接开始讲解FIRST&#xff1a;如何抽象出动态规划算法&#xff1f;这个问题&#xff0c;困扰了无数代OIER&#xff0c;包括本蒟蒻在比赛的时候&#xff0c;看一道题&#xff0c;怎么想到他是什么算法的呢&#xff1f;这就需要抽象能力而不同的算法&#xff0c;往往有着不同…

The last packet sent successfully to the server was 0 milliseconds ago. 解决办法

mybatis-generator-maven-plugin插件The last packet sent successfully to the server was 0 milliseconds agoYou must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to…

Spark SQL 介绍

文章目录Spark SQL1、Hive on SparkSQL2、SparkSQL 优点3、SparkSQL 特点1) 容易整合2) 统一的数据访问3) 兼容 Hive4) 标准的数据连接4、DataFrame 是什么5、DataSet 是什么Spark SQL Spark SQL 是 Spark 用于结构化数据(structured data) 处理的Spark模块。 1、Hive on Spa…

维基百科数据抽取

1. 数据路径 https://dumps.wikimedia.org/enwiki/latest/ ----英文 https://dumps.wikimedia.org/zhwiki/latest/ ----中文 https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2 --下载最新的 https://dumps.wikimedia.org/wikidatawiki/2023…