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:负责解析网页内容,并从中提取数据
所以它们常常一起出现:
- 先用
requests.get()拿到 HTML - 再用
BeautifulSoup()把 HTML 解析成对象 - 最后用各种选择器提取需要的数据
一句话记住:
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.h1、find()、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")当然能找到一堆链接,但里面往往混着:
- 导航栏链接
- 广告链接
- 相关文章链接
- 正文链接
- 页脚链接
最后数据会很乱。
更好的做法是:
- 先找到列表区域
- 再在这个区域里找标题、链接、作者、时间
也就是说,尽量从:
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,不建议只看语法。
更好的学习顺序是:
- 先用本地 HTML 字符串练
find()、find_all()、select() - 再学
requests.get()把网页拿下来 - 再自己挑一个结构简单的页面练手
- 把提取结果整理成字典或列表
- 最后导出成 JSON、CSV 或写入数据库
你会发现,真正的能力不是“会几个 API”,而是:
看到一个网页,能快速判断该从哪里切入提取数据。
15. 总结
BeautifulSoup 是 Python 生态里非常经典、也非常适合新手入门的网页解析库。
它最大的价值不是“语法多高级”,而是把网页提取这件事变得直观了很多。
记住这套组合最核心的分工:
requests:负责抓网页BeautifulSoup:负责拆网页- 你的 Python 代码:负责整理数据和后续处理
如果你正在学习 Python,又希望尽快做出一些“能解决实际问题”的小工具,那么 BeautifulSoup 非常值得你亲手写一遍。
先从本地 HTML 开始,跑通选择器,再去抓真实网页,你的进步会快很多。