news 2026/4/28 16:31:22

Python BeautifulSoup 入门教程:快速学会抓取和解析网页数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python BeautifulSoup 入门教程:快速学会抓取和解析网页数据

Python BeautifulSoup 入门教程:快速学会抓取和解析网页数据

很多 Python 初学者学完基础语法之后,都会很自然地遇到一个问题:

我能不能把网页里的内容提取下来,变成自己能处理的数据?

比如:

  • 抓取文章标题
  • 提取商品名称和价格
  • 收集招聘信息
  • 批量整理博客链接
  • 分析网页中的表格和列表

这时候,BeautifulSoup往往就是最适合入门的工具之一。

它不像大型爬虫框架那样一上来就有很多工程化概念,也不像正则表达式那样容易把人绕晕。它做的事情很纯粹:

帮你解析 HTML,然后从中提取你真正需要的数据。

如果你现在正在学习 Python,又想快速上手网页数据抓取,这篇文章会非常适合你。我们会从 0 开始讲清楚:

  • BeautifulSoup 到底是什么
  • 它和requests是什么关系
  • 如何抓取网页 HTML
  • 如何用find()find_all()select()提取数据
  • 如何写出一个完整的小型抓取脚本
  • 实际使用时有哪些坑要提前避开

1. BeautifulSoup 是什么

BeautifulSoup是一个专门用来解析 HTML / XML 文档的 Python 库。

你可以把它理解成一个“网页内容整理器”。

网页源码本来是一大段字符串,里面夹杂了很多标签,比如:

<divclass="article"><h2>Python 入门</h2><ahref="/post/1">查看详情</a></div>

如果你直接拿字符串去切片、用正则硬抠,代码会非常脆弱。

而 BeautifulSoup 会先把这段 HTML 解析成一个结构化对象,然后你就可以像查树节点一样去找:

  • 某个标签
  • 某个 class
  • 某个 id
  • 某个属性
  • 某个标签里的文本

这也是它名字里Soup的感觉所在。原本很乱的网页源码,会被它整理成更容易“舀出来”的结构。

2. BeautifulSoup 和 requests 是什么关系

很多新手刚接触网页抓取时,最容易混淆这两个库。

其实职责非常清楚:

  • requests:负责向网站发请求,把网页内容下载回来
  • BeautifulSoup:负责解析网页内容,并从中提取数据

所以它们常常一起出现:

  1. 先用requests.get()拿到 HTML
  2. 再用BeautifulSoup()把 HTML 解析成对象
  3. 最后用各种选择器提取需要的数据

一句话记住:

requests 管“拿网页”,BeautifulSoup 管“拆网页”。

3. 先安装依赖

直接安装 BeautifulSoup:

pipinstallbeautifulsoup4

实际抓取网页时,通常还会配合requests

pipinstallrequests beautifulsoup4

如果你后面想让解析速度更快,也可以安装lxml作为解析器:

pipinstalllxml

不过对初学者来说,先用 Python 自带的html.parser就够了。

4. BeautifulSoup 最基础的使用方式

先不要急着抓真实网站,先用一段本地 HTML 练手,这样最容易理解。

frombs4importBeautifulSoup html=""" <html> <body> <h1>Python 学习笔记</h1> <p class="desc">这是一个 BeautifulSoup 示例页面</p> <a href="/post/1">第一篇文章</a> <a href="/post/2">第二篇文章</a> </body> </html> """soup=BeautifulSoup(html,"html.parser")print(soup.h1.get_text())print(soup.find("p",class_="desc").get_text())

这段代码里最关键的是:

soup=BeautifulSoup(html,"html.parser")

它表示把字符串形式的 HTML 交给 BeautifulSoup 解析。

后面你就可以通过soup.h1find()select()这些方式去拿数据。

5. 先掌握最常用的 4 个操作

BeautifulSoup 的 API 不算少,但对于新手来说,真正最常用的就这几个。

5.1find():找第一个匹配标签

title=soup.find("h1")print(title.get_text())

如果页面里有多个h1,它只会返回第一个匹配项。

你也可以加属性条件:

desc=soup.find("p",class_="desc")

注意这里是class_,后面要加下划线,因为class是 Python 关键字。

5.2find_all():找所有匹配标签

links=soup.find_all("a")forlinkinlinks:print(link.get_text(),link.get("href"))

这个方法非常适合提取列表数据,比如:

  • 所有文章链接
  • 所有商品卡片
  • 所有招聘项

5.3select():用 CSS 选择器查找

如果你有一点前端基础,会非常喜欢这个方法。

items=soup.select("a")desc=soup.select_one("p.desc")

常见写法:

  • div:选所有div
  • .card:选 class 为card的元素
  • #main:选 id 为main的元素
  • .article-list a:选某个区域下面的所有链接

在很多实际项目中,select()select_one()会比find()更顺手。

5.4get_text()get()

提取文本:

text=title.get_text(strip=True)

提取属性:

href=link.get("href")

这里要区分清楚:

  • get_text():拿标签里的文字
  • get("href"):拿标签属性

6. 写一个稍微像样一点的解析示例

下面这段示例会更接近真实项目。

我已经把完整代码整理成单独文件,方便你本地直接运行:

beautifulsoup_web_scraping_demo.py

代码如下:

from__future__importannotationsfrombs4importBeautifulSoupimportrequests SAMPLE_HTML=""" <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <title>BeautifulSoup Demo</title> </head> <body> <div class="article-list"> <article class="article-card">defparse_local_html()->list[dict[str,str]]:soup=BeautifulSoup(SAMPLE_HTML,"html.parser")articles:list[dict[str,str]]=[]forcardinsoup.select(".article-card"):link=card.select_one(".title a")author=card.select_one(".author")views=card.select_one(".views")iflinkisNoneorauthorisNoneorviewsisNone:continuearticles.append({"id":card.get("data-id",""),"title":link.get_text(strip=True),"url":link.get("href",""),"author":author.get_text(strip=True),"views":views.get_text(strip=True),})returnarticlesdeffetch_page_title(url:str)->str:headers={"User-Agent":("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ""AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/124.0 Safari/537.36")}response=requests.get(url,headers=headers,timeout=10)response.raise_for_status()soup=BeautifulSoup(response.text,"html.parser")ifsoup.titleandsoup.title.string:returnsoup.title.string.strip()return"页面没有 title"defmain()->None:print("本地 HTML 解析结果:")foriteminparse_local_html():print(item)# 真实抓取时,把这里替换成你自己的目标网页。# 使用前请先确认目标站点允许抓取,并控制请求频率。# title = fetch_page_title("https://example.com")# print("页面标题:", title)if__name__=="__main__":main()

这个示例故意分成两部分:

  • parse_local_html():先教你专注理解 BeautifulSoup 的解析过程
  • fetch_page_title():再告诉你如何把真实网页抓下来后交给 BeautifulSoup

学习这类东西时,建议你也这么练:

先会“解析”,再会“抓取”,最后再把两者组合。

7. 真实抓取网页时的标准流程

很多网站的抓取逻辑,本质上都可以拆成下面这几步:

第一步:发送请求

importrequests response=requests.get(url,timeout=10)html=response.text

第二步:构造 BeautifulSoup 对象

frombs4importBeautifulSoup soup=BeautifulSoup(html,"html.parser")

第三步:定位数据区域

cards=soup.select(".article-card")

第四步:从每个区域中提取字段

forcardincards:title=card.select_one(".title").get_text(strip=True)link=card.select_one("a").get("href")

第五步:整理成结构化数据

data.append({"title":title,"url":link,})

所以你会发现,BeautifulSoup 真正的核心工作其实是:

先找到“每条数据的边界”,再从每条记录里拆字段。

这也是写抓取脚本时最重要的思维方式。

8. 新手最常见的一个误区:一上来就抓整页

刚开始学网页抓取时,很多人喜欢一上来就对整页所有标签乱搜。

例如页面里有几十个a标签,你直接:

soup.find_all("a")

当然能找到一堆链接,但里面往往混着:

  • 导航栏链接
  • 广告链接
  • 相关文章链接
  • 正文链接
  • 页脚链接

最后数据会很乱。

更好的做法是:

  1. 先找到列表区域
  2. 再在这个区域里找标题、链接、作者、时间

也就是说,尽量从:

soup.select(".article-card")

这种“按块定位”的方式入手,而不是全页面乱抓。

9. BeautifulSoup 常见解析器怎么选

创建对象时你会看到第二个参数:

BeautifulSoup(html,"html.parser")

这里指定的是解析器。

常见的有三个:

  • html.parser:Python 自带,安装最省事
  • lxml:速度通常更快,项目里很常用
  • html5lib:容错更强,但一般更重

如果你是初学者:

  • 学习阶段先用html.parser
  • 后面项目里再考虑lxml

先跑通流程,比一开始纠结性能更重要。

10. 为什么有时抓不到你在浏览器里看到的内容

这是 BeautifulSoup 初学者非常容易遇到的坑。

你在浏览器里明明看到了内容,但requests.get()拿回来的 HTML 里却没有。

原因通常是:

页面的数据是通过 JavaScript 动态加载的。

也就是说,浏览器打开页面后,还会继续执行 JS,再向接口请求数据,最后才把内容渲染出来。

requests拿到的只是最初的 HTML。

这时候 BeautifulSoup 没问题,问题在于你抓到的输入源就不完整。

遇到这种情况,常见思路有两个:

  • 直接分析网页接口,改抓接口返回的 JSON
  • 使用 Playwright、Selenium 这类浏览器自动化工具

所以要记住:

BeautifulSoup 擅长解析 HTML,但它不会替你执行前端 JavaScript。

11. 实战中必须注意的几个问题

这部分比语法更重要。

11.1 不要把网页抓取理解成“复制粘贴源码”

真正的抓取工作,不是看到标签就抄代码,而是要先观察页面结构:

  • 每条数据的容器是什么
  • 标题在哪个标签
  • 链接在哪个属性
  • 时间、作者、价格是否都在固定位置

只有先分析结构,BeautifulSoup 才会变得好用。

11.2 记得加请求头

有些网站对默认请求不友好,最简单的处理就是带一个常见浏览器的User-Agent

headers={"User-Agent":"Mozilla/5.0 ..."}response=requests.get(url,headers=headers,timeout=10)

11.3 记得处理异常

不要默认所有请求都会成功。

response.raise_for_status()

至少先把 HTTP 错误暴露出来,否则你很可能在拿一个报错页做解析。

11.4 控制抓取频率

如果你需要抓取多页内容,不要用极高频率连续请求。

这不仅容易失败,也可能给目标网站带来压力。

11.5 尊重站点规则和数据边界

在使用 BeautifulSoup 抓取网页数据前,应该先确认目标站点的使用条款、robots 规则以及数据使用边界。

技术上能抓,不代表业务上就一定适合抓。

12. BeautifulSoup 适合哪些场景

BeautifulSoup 非常适合下面这些任务:

  • 网页结构比较稳定
  • 页面主要内容就在 HTML 中
  • 抓取规模不算特别大
  • 想快速写一个轻量脚本
  • 想先验证网页数据能不能提取

比如:

  • 文章列表抓取
  • 简单商品页抓取
  • 博客导航页整理
  • 表格数据提取
  • 页面链接分析

如果你只是想先把网页数据提下来,再做后续分析处理,BeautifulSoup 是一个很好的起点。

13. BeautifulSoup 和 Scrapy 该怎么选

这个问题很多人都会问。

可以这样理解:

  • BeautifulSoup 更像“解析工具”
  • Scrapy 更像“完整爬虫框架”

如果你的需求是:

  • 抓 1 个到几十个页面
  • 快速写脚本验证
  • 重点在网页解析本身

那么requests + BeautifulSoup会更轻、更直接。

如果你的需求是:

  • 大量分页抓取
  • 自动跟进链接
  • 需要统一导出、调度、去重、重试

那通常就要考虑 Scrapy 了。

所以 BeautifulSoup 并不是“低配版 Scrapy”,而是更适合入门和轻量场景的工具。

14. 给初学者的学习建议

如果你想真正学会 BeautifulSoup,不建议只看语法。

更好的学习顺序是:

  1. 先用本地 HTML 字符串练find()find_all()select()
  2. 再学requests.get()把网页拿下来
  3. 再自己挑一个结构简单的页面练手
  4. 把提取结果整理成字典或列表
  5. 最后导出成 JSON、CSV 或写入数据库

你会发现,真正的能力不是“会几个 API”,而是:

看到一个网页,能快速判断该从哪里切入提取数据。

15. 总结

BeautifulSoup 是 Python 生态里非常经典、也非常适合新手入门的网页解析库。

它最大的价值不是“语法多高级”,而是把网页提取这件事变得直观了很多。

记住这套组合最核心的分工:

  • requests:负责抓网页
  • BeautifulSoup:负责拆网页
  • 你的 Python 代码:负责整理数据和后续处理

如果你正在学习 Python,又希望尽快做出一些“能解决实际问题”的小工具,那么 BeautifulSoup 非常值得你亲手写一遍。

先从本地 HTML 开始,跑通选择器,再去抓真实网页,你的进步会快很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/28 16:29:34

制造业物料管理系统怎么选?10大好用物料管理系统盘点!

在制造业数字化转型的浪潮中&#xff0c;选择一款合适的制造业物料管理系统已成为企业提升生产效率、控制成本、优化供应链的核心任务。面对市场上琳琅满目的物料管理系统&#xff0c;许多企业管理者都陷入了“怎么选”的困惑。一个好的物料管理系统不仅能打通研发、生产、采购…

作者头像 李华
网站建设 2026/4/28 16:27:21

GaussianBev + REVFormer:3D 高斯表示 + 可逆 Transformer BEV 分割

文章目录 GaussianBev + REVFormer:3D 高斯表示 + 可逆 Transformer BEV 分割 一、任务 二、GaussianBev 原理 2.1 3D Gaussian Splatting 表示 2.2 Lift: 像素 → 3D 高斯 2.3 Splat: 高斯 → BEV 网格 三、REVFormer 原理 3.1 可逆 Transformer 3.2 逆向 四、模型 4.1 Gauss…

作者头像 李华
网站建设 2026/4/28 16:26:20

手机拍照太暗有救了!深入浅出解读Zero-DCE低光增强算法

手机拍照太暗有救了&#xff01;深入浅出解读Zero-DCE低光增强算法 你是否曾在昏暗的餐厅、夜晚的街头或光线不足的室内&#xff0c;用手机拍下一张照片&#xff0c;却发现画面漆黑一片、细节全无&#xff1f;这种令人沮丧的体验即将成为过去。今天&#xff0c;我们要介绍一项革…

作者头像 李华
网站建设 2026/4/28 16:24:50

终极CPP抢票指南:3步轻松搞定热门漫展门票

终极CPP抢票指南&#xff1a;3步轻松搞定热门漫展门票 【免费下载链接】cppTickerBuy cpp cp30 漫展 活动 抢票 无差别 同人展 项目地址: https://gitcode.com/gh_mirrors/cp/cppTickerBuy 还在为抢不到心仪的CPP漫展门票而烦恼吗&#xff1f;cppTickerBuy作为一款开源免…

作者头像 李华
网站建设 2026/4/28 16:17:32

Simulink建模玩不转?试试用S函数手把手复现Lugre摩擦模型(附完整代码)

从Simulink到S函数&#xff1a;Lugre摩擦模型的代码化实现与工程实践 在动力学系统仿真领域&#xff0c;摩擦模型一直是影响仿真精度的关键因素之一。Lugre摩擦模型因其能够准确描述静摩擦到动摩擦的过渡特性&#xff0c;被广泛应用于机械系统、机器人控制和精密定位等领域。传…

作者头像 李华