如何使用BeautifulSoup库来提取HTML中的特定元素

前言

爬虫拿到HTML源码之后,最核心的工作就是提取特定元素、文本、链接 。BeautifulSoup4(bs4)提供多种方式定位页面标签:标签名搜索、class/id匹配、属性过滤、CSS选择器。CSS选择器select()/select_one()日常开发用得最多,写法简洁直观。

前置依赖

复制代码
pip install beautifulsoup4 lxml

from bs4 import BeautifulSoup

html_sample = """
<div class="table-wrap">
    <div class="item row">
        <div class="title">标准编号:GB50017‑2003</div>
        <div class="type">国家标准</div>
        <a href="/detail?id=1001" class="link">查看详情</a>
    </div>
    <div class="item row">
        <div class="title">标准编号:GB50405‑2007</div>
        <div class="type">国家标准</div>
        <a href="/detail?id=1002" class="link">查看详情</a>
    </div>
</div>
"""
# 加载HTML文档
soup = BeautifulSoup(html_sample, "lxml")

1. find():提取第一个匹配的元素

find(标签名, 属性条件),找到第一个匹配节点,找不到返回None,不会抛异常。

复制代码
# 查找第一个class="item row"的div节点
tag = soup.find("div", class_="item row")
if tag:
    print(tag.get_text(strip=True))

# 根据id查找
soup.find(id="table-wrap")

# 根据自定义属性过滤,比如 data‑xxx
soup.find("a", attrs={"class":"link"})

⚠️注意:class是Python关键字,参数要写class_=,末尾带下划线。

2. find_all():提取全部匹配元素,返回列表

返回所有符合条件节点组成的列表,没有匹配返回空列表[]

复制代码
# 获取全部 class="item row" 的div
item_list = soup.find_all("div", class_="item row")
for item in item_list:
    text = item.get_text(strip=True)
    print(text)

# 限制返回数量,只取前1条
item_list = soup.find_all("div", class_="item row", limit=1)

3. CSS选择器 select / select_one(最推荐)

select_one():匹配第一个 ,无结果返回None

select():匹配全部,返回节点列表

语法和网页CSS完全一致:

  • .类名 → class筛选

  • #id值 → id筛选

  • 标签名 → 标签筛选

  • 父标签 > 子标签 → 直接子元素

  • 父标签 子标签 → 后代所有子元素

    取第一个 .item.row

    first_item = soup.select_one(".item.row")

    获取全部 .item.row

    all_items = soup.select(".item.row")

    获取 .item 下面所有a标签

    link_tags = soup.select(".item.row a.link")

    直接子元素 >

    title_div = soup.select_one(".item.row > .title")

4. 拿到元素之后:提取文本、属性

提取文本

复制代码
tag = soup.select_one(".title")

# get_text() 推荐,支持参数控制
text1 = tag.get_text(strip=True)          # 去除前后换行空格
text2 = tag.get_text(strip=True, separator=" ") # 子节点文本用空格隔开

# 不推荐 .text ,无法做strip处理
# text = tag.text

提取标签属性(href、src、style等)

优先使用.get(),属性不存在返回None,不会抛出KeyError

复制代码
a_tag = soup.select_one("a.link")
href = a_tag.get("href")   # ✅ 安全,无属性返回None

# 不推荐直接下标取值,没有属性直接报错
# href = a_tag["href"]

# 获取全部属性字典
attr = a_tag.attrs
print(attr)

5. 实战示例:循环提取多条列表数据

以上面示例html,循环取出每条的标题、类型、链接:

复制代码
item_list = soup.select(".item.row")
result = []
for item in item_list:
    title = item.select_one(".title").get_text(strip=True)
    std_type = item.select_one(".type").get_text(strip=True)
    link = item.select_one(".link").get("href")
    result.append({
        "title": title,
        "std_type": std_type,
        "link": link
    })
print(result)

6. 结合requests网页真实场景

复制代码
import requests
from bs4 import BeautifulSoup

resp = requests.get("[https://example.com](https://example.com)")
soup = BeautifulSoup(resp.text, "lxml")

# 提取页面所有a标签链接
for a in soup.select("a"):
    url = a.get("href")
    print(url)

7. 常见踩坑点

  1. 判空! find() / select_one() 找不到返回None,直接调用.get_text()会报AttributeError

    tag = soup.select_one(".not‑exist")
    if tag is not None:
    txt = tag.get_text(strip=True)

  2. class有多个值时:class="item row",bs4中class_="item row"可以匹配;CSS选择器写.item.row(中间无空格)。

  3. 不要用正则去解析HTML,标签嵌套、属性顺序变化,正则极易失效。

  4. select()永远返回列表,哪怕只有一条数据,需要用下标[0]或者改用select_one()

  5. 网页残缺、标签不闭合,lxml解析器容错能力强,优先使用。

find/find_all 和 select/select_one怎么选

方式 优点 缺点
find / find_all 原生API,支持复杂属性过滤 写多层嵌套比较繁琐
select / select_one CSS选择器,写法简短,前端开发易上手 部分复杂属性匹配不如find灵活

日常爬虫开发优先使用selectselect_one

相关推荐
IT毕设梦工厂1 小时前
计算机毕业设计选题推荐:基于大数据的城市空气污染物浓度数据分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·python·信息可视化·数据挖掘·数据分析·课程设计·数据可视化
程序员阿黄1 小时前
基于 Django 与 Vue 3 的智能实验室预约系统设计与实现
后端·python·mysql·django·vue·毕设
用户298698530141 小时前
Python 如何实现 Word 与 RTF 文档互转
后端·python·api
程序猿在线码字1 小时前
深度学习(一)
python·深度学习·神经网络·机器学习
打工仔折腾 AI2 小时前
用 Shell 脚本自动部署 mysqld_exporter 并接入 Prometheus 远程抓取
人工智能·后端·python·性能优化·ai agent 实战
梦想不只是梦与想2 小时前
环境管理:Conda 与 venv
python·conda·uv
Yolanda_20222 小时前
6.pytorch加载数据初认识
python
更深兼春远2 小时前
Python到底怎么用于测试?
自动化测试·软件测试·python·接口测试
我不会起名字3222 小时前
一天一道力扣Hot100(36):深度优先算法---组合总和
数据结构·c++·后端·python·算法·go