Python爬虫之BeautifulSoup模块

Python爬虫之BeautifulSoup模块

在网络爬虫的世界里,获取网页内容只是第一步。真正的挑战在于从HTML的大海中提取出你需要的信息。这就是BeautifulSoup发光发热的地方。作为Python中最受欢迎的HTML解析库之一,BeautifulSoup以其强大的功能和易用性赢得了众多开发者的青睐。

什么是BeautifulSoup?

BeautifulSoup是一个Python库,专门用于从HTML和XML文件中提取数据。它的名字来源于一个古老的笑话:“一天,有人说:‘我做了一碗美丽的汤。这是最美的汤。在这碗汤里,我把所有漂亮的东西都放进去了。’”——就像这碗"汤"一样,BeautifulSoup将所有的HTML元素都放进一个整洁的数据结构中,让你轻松地找到并提取任何你需要的"配料"。

  • 强大:可以处理杂乱、不规范的HTML。
  • 灵活:支持多种解析器,如lxml、html.parser、html5lib等。
  • 直观:使用类似于CSS选择器和正则表达式的方法来查找和操作元素。
  • 流行:在GitHub上拥有超过10,000颗星,是爬虫开发者的首选工具之一。

安装和基本使用

安装BeautifulSoup非常简单:

pip install beautifulsoup4

让我们从一个简单的例子开始:

from bs4 import BeautifulSouphtml_doc = """
<html><head><title>我的博客</title></head><body><h1>欢迎来到我的博客</h1><p class="intro">这是一个关于Python的博客。</p><div id="posts"><h2>最新文章</h2><ul><li><a href="/bs4">BeautifulSoup教程</a></li><li><a href="/flask">Flask入门</a></li></ul></div></body>
</html>
"""soup = BeautifulSoup(html_doc, 'html.parser')# 打印网页标题
print(soup.title.string)  # 输出: 我的博客# 找到第一个 <p> 标签
print(soup.p.string)  # 输出: 这是一个关于Python的博客。# 找到所有的链接
for link in soup.find_all('a'):print(link.get('href'))  # 输出: /bs4 和 /flask

导航DOM树

BeautifulSoup将HTML解析为一个树状结构,这使得导航变得非常直观:

  • .contents:获取一个元素的直接子元素列表。
  • .children:子元素的迭代器,适合大文档。
  • .parent:获取一个元素的父元素。
  • .next_sibling & .previous_sibling:在同级元素中导航。
# 查找h1的父元素
body = soup.h1.parent
print(body.name)  # 输出: body# 获取ul的所有子元素
ul = soup.find('ul')
for child in ul.children:print(child.name)  # 输出: li (两次,因为有两个<li>标签)# 在兄弟元素间导航
first_li = soup.find('li')
next_li = first_li.next_sibling.next_sibling  # 跳过空白文本节点
print(next_li.a.string)  # 输出: Flask入门

搜索DOM树

BeautifulSoup提供了强大的搜索方法来找到你需要的元素:

1. find() & find_all()

  • find():返回第一个匹配的元素。
  • find_all():返回所有匹配的元素。
# 找到所有<h2>标签
for h2 in soup.find_all('h2'):print(h2.string)  # 输出: 最新文章# 找到id为'posts'的元素
posts = soup.find(id='posts')
print(posts.h2.string)  # 输出: 最新文章

2. CSS选择器

如果你熟悉CSS,你会爱上BeautifulSoup的.select()方法:

# 使用CSS选择器
intro = soup.select_one('p.intro')
print(intro.string)  # 输出: 这是一个关于Python的博客。# 更复杂的选择器
for item in soup.select('div#posts ul li a'):print(item.string)  # 输出: BeautifulSoup教程 和 Flask入门

3. 按属性搜索

你可以使用关键字参数或attrs字典来按属性搜索:

# 找到所有带有href属性的<a>标签
for link in soup.find_all('a', href=True):print(link['href'])  # 输出: /bs4 和 /flask# 使用正则表达式
import re
for link in soup.find_all('a', href=re.compile(r'^/[a-z]+')):print(link['href'])  # 同样输出: /bs4 和 /flask

4. 文本搜索

有时你只想根据文本内容来查找:

# 查找包含"Flask"的任何标签
flask_items = soup.find_all(string=re.compile("Flask"))
for item in flask_items:print(item)  # 输出: Flask入门

修改DOM树

BeautifulSoup不仅可以读取HTML,还可以修改它:

# 修改标题
soup.title.string = "BeautifulSoup教程"# 添加新标签
new_link = soup.new_tag("a", href="/pandas")
new_link.string = "Pandas数据分析"
soup.ul.append(new_link)# 删除一个元素
to_delete = soup.select_one('a[href="/flask"]').parent
to_delete.decompose()print(soup.prettify())  # 打印美化后的HTML

实战:解析新闻网站

让我们把学到的知识应用到一个实际的例子中。假设我们正在爬取一个科技新闻网站:

html = """
<div class="news-container"><div class="top-story"><h1><a href="/ai-beats-human">AI在围棋比赛中再次击败人类冠军</a></h1><p class="summary">DeepMind的AlphaGo程序以4:1的比分战胜围棋世界冠军。</p><span class="date">2024-06-05</span></div><ul class="other-news"><li><a href="/python-4">Python 4.0发布,性能提升50%</a><span class="date">2024-06-03</span></li><li><a href="/web-scraping">网络爬虫:互联网的数据考古学家</a><span class="date">2024-06-01</span></li></ul>
</div>
"""soup = BeautifulSoup(html, 'html.parser')# 提取头条新闻
top_story = soup.select_one('.top-story')
headline = top_story.h1.a.string
headline_link = top_story.h1.a['href']
summary = top_story.select_one('.summary').string
headline_date = top_story.select_one('.date').stringprint(f"头条: {headline} ({headline_link})")
print(f"摘要: {summary}")
print(f"日期: {headline_date}\n")# 提取其他新闻
print("其他新闻:")
for item in soup.select('.other-news li'):title = item.a.stringlink = item.a['href']date = item.select_one('.date').stringprint(f"- {title} ({link}) - {date}")

这个例子展示了BeautifulSoup的强大功能:

  1. 使用CSS选择器(.top-story, .summary)精确定位元素。
  2. 轻松提取属性(a['href'])和文本内容(.string)。
  3. 使用循环和选择器(.other-news li)处理列表项。

通过这种方式,我们可以从任何结构化良好的网页中提取信息,无论是新闻、产品列表、论坛帖子还是其他任何内容。

性能考虑

虽然BeautifulSoup非常强大和灵活,但它并不是最快的解析器。如果速度是你的首要考虑,可以考虑以下几点:

  1. 选择更快的解析器:

    # lxml比默认的html.parser快
    soup = BeautifulSoup(html, 'lxml')
    
  2. 对于非常大的文档,考虑使用lxml库直接进行XPath查询。

  3. 如果只需要少量特定数据,正则表达式可能更快,但要小心使用,因为HTML的结构可能会改变。

总结

BeautifulSoup是Python网页解析领域的一颗明星。凭借其直观的API、强大的查询能力和对糟糕HTML的容错性,它几乎可以处理任何网页解析任务。我们已经看到它如何优雅地导航和搜索DOM树、修改HTML结构以及从复杂的网页中提取信息。

无论你是在进行数据挖掘、构建一个元搜索引擎还是仅仅想自动化一些网页阅读任务,BeautifulSoup都是你的得力助手。它让从互联网的海洋中捞取珍珠变得如此简单,难怪它会成为每个Python开发者工具箱中的必备工具。

所以下次当你面对一个HTML大杂烩时,不要慌:倒一碗BeautifulSoup,任何数据都将乖乖就范!

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

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

相关文章

基于包围盒的机械臂防碰撞算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 5.完整工程文件 1.课题概述 基于包围盒的机械臂防碰撞算法。在实际情况中&#xff0c;由于很多对象结构较为复杂&#xff0c;当目标对象与障碍物之间的包围盒相交的时候&#xff0c;而两个物体并不相交。这就需要进一步划…

初始化git项目,并推送到github上

git推送到github上 要将当前的Git项目推送到GitHub上&#xff0c;可以按照以下步骤进行操作&#xff1a; 在GitHub上创建一个新的仓库。请确保你已经登录到你的GitHub账号&#xff0c;并点击页面右上角的" New repository"按钮来创建一个新的仓库。根据提示填写仓库…

js 一维数组转多维数组

效果图&#xff1a; //源数组const arrList [{"id": 1,"code": "001","name": "第一个","parentCode": "",},{"id": 2,"code": "00101","name": "第一…

嵌入式系统日志轮转:实现与性能考量

日志轮转是嵌入式系统中管理日志文件的一种常用技术&#xff0c;它通过创建新的日志文件来替代旧的日志文件&#xff0c;从而避免日志文件无限增长&#xff0c;占用过多存储空间。本文将探讨日志轮转的实现方法以及在嵌入式系统中实现日志轮转时需要考虑的性能因素。 一、日志…

springboot项目中第三方jar包打包进jar包

springboot项目中&#xff0c;如果手动引入了jar包&#xff0c;打包时不会将手动引入的第三方jar包打包进价包里&#xff0c;如何处理&#xff1f; 若第三方的jar包的lib和src同级&#xff0c;则maven打包时默认不会将lib下的jar包打包进jar包&#xff0c;处理方式有两种&#…

Golang | Leetcode Golang题解之第133题克隆图

题目&#xff1a; 题解&#xff1a; func cloneGraph(node *Node) *Node {if node nil {return node}visited : map[*Node]*Node{}// 将题目给定的节点添加到队列queue : []*Node{node}// 克隆第一个节点并存储到哈希表中visited[node] &Node{node.Val, []*Node{}}// 广…

nginx --- 反向代理|负载均衡 | 动静分离

目录 反向代理如何配置 1、反向代理实例一 2、反向代理实例二 ocation 指令说明 Nginx 负载均衡 负载均衡常用算法 应用场景 总结 Nginx实现动静分离 一、什么是动静分离 二、实现方案 三、配置Nginx动静分离 四、验证测试 反向代理如何配置 1、反向代理实例一 实…

视频怎么压缩变小?推荐三个压缩方法

视频怎么压缩变小&#xff1f;在数字时代&#xff0c;视频已成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;随着视频质量的提升&#xff0c;视频文件的大小也随之增加&#xff0c;这给存储和分享带来了不小的挑战。幸运的是&#xff0c;市面上有许多视频压缩软件…

2024首发!会声会影2024旗舰版,专业编辑新体验!

会声会影2024最新旗舰版是一款专业的视频编辑软件&#xff0c;它集成了多种高级功能&#xff0c;为用户带来极致的视频编辑体验。在这篇文章中&#xff0c;我们将详细介绍该软件的功能和特色&#xff0c;帮助用户更好地了解和使用它。 会声会影全版本绿色安装包获取链接&#…

【简单理解化】 内存函数及它的模拟实现

本文章谈论memcpy,memcmp,memmove,memset函数 目录 1.memcpy的使用和模拟实现 2.memmove的使用和模拟实现 3.memset的使用 4.memcmp函数的使用 1.memcpy的使用和模拟实现 该函数用于从源内存块复制指定数量的字节到目标内存块 1 void * memcpy ( void * destination, const voi…

【机器学习基础】Python编程01:五个实用练习题的解析与总结

Python是一种广泛使用的高级编程语言,它在机器学习领域中的重要性主要体现在以下几个方面: 简洁易学:Python语法简洁清晰,易于学习,使得初学者能够快速上手机器学习项目。 丰富的库支持:Python拥有大量的机器学习库,如scikit-learn、TensorFlow、Keras和PyTorch等,这些…

ubuntu 18.04 arm install ravens error

GitHub - google-research/ravens: Train robotic agents to learn pick and place with deep learning for vision-based manipulation in PyBullet. Transporter Nets, CoRL 2020. 安装环境&#xff1a;xaiver ubuntu18.04 1、install python 2、install mimiconda,这里要…

Windows系统中配置 Redis 监听特定的 IP 地址

步骤 1:安装 Redis for Windows 从 Redis 官方网站 或 Microsoft Open Tech 下载适用于 Windows 的 Redis 版本。解压缩下载的压缩包到一个目录,比如 C:\Redis。打开命令提示符(以管理员身份运行),导航到 Redis 目录并启动 Redis 服务器:cd C:\Redis redis-server.exe步骤…

分布式搜索引擎ElasticSearch学习笔记

一、Elasticsearch介绍 什么是elasticsearch&#xff1f; 一个开源的分布式搜索引擎&#xff0c;可以用来实现搜索、日志统计、分析、系统监控等功能 什么是elastic stack&#xff08;ELK&#xff09;&#xff1f; 是以elasticsearch为核心的技术栈&#xff0c;包括beats、…

构建LangChain应用程序的示例代码:19、自定义多动作代理教程(Custom multi-action agent)

自定义多动作代理 概述 这个笔记本介绍了如何创建您自己的自定义代理。 代理由两部分组成&#xff1a; 工具&#xff08;Tools&#xff09;&#xff1a;代理可以使用的工具。代理类本身&#xff1a;决定采取哪个动作。 在这个笔记本中&#xff0c;我们将通过创建一个自定义…

C++ | Leetcode C++题解之第134题加油站

题目&#xff1a; 题解&#xff1a; class Solution { public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int n gas.size();int i 0;while (i < n) {int sumOfGas 0, sumOfCost 0;int cnt 0;while (cnt < n) {int j (i …

2.1.3 采用接口方式使用MyBatis

实战概述&#xff1a;使用MyBatis的接口方式进行数据库操作 环境准备 确保项目中已经集成了MyBatis框架。 创建用户映射器接口 在net.huawei.mybatis.mapper包中创建UserMapper接口。定义方法findById(int id)用于按编号查询用户。定义方法findAll()用于查询全部用户。定义方法…

嵌入式Linux系统中GPIO应用控制详解

大家好,今天主要和大家分享一下,如何在linux系统上,实现GPIO口的控制,其中GPIO在内核端基本操作如下。 第一:Linux系统中GPIO介绍 GPIO(General-Purpose IO Ports),即通用I0接口.GPIO的使用较为简单,主要分为输入和输出两种功能.GPIO主要用于实现一些简单设备的控制.…

3. 使用tcpdump抓取rdma数据包

系列文章 第1章 多机多卡运行nccl-tests 和channel获取第2章 多机多卡nccl-tests 对比分析第3章 使用tcpdump抓取rdma数据包 目录 系列文章一、准备工作1. 源码编译tcpdump2. 安装wireshark 二、Tcpdump抓包三、Wireshark分析 一、准备工作 1. 源码编译tcpdump 使用 tcpdump…

判断经纬度是否在某个城市内

一、从高德获取指定城市边界经纬度信息 通过apifox操作&#xff1a; 二、引入第三方jar包&#xff1a; maven地址&#xff1a;https://mvnrepository.com/ maven依赖&#xff1a; <dependency><groupId>org.locationtech.jts</groupId><artifactId>…