目录
前置知识
我们的任务是编写一个程序,来查找给定网站 URL 中所有的 CSS 类(class)。在 BeautifulSoup 中,并没有一个直接内置的方法可以一次性找到所有的类,不过别担心,我们可以通过几种方式来实现这个目标。
所需模块
- bs4:Beautiful Soup (bs4) 是一个 Python 库,专门用于从 HTML 和 XML 文件中提取数据。这个模块不是 Python 内置的。要安装它,请在终端中输入以下命令。
pip install bs4
- requests:Requests 库允许我们极其轻松地发送 HTTP/1.1 请求。这个模块也不是 Python 内置的。要安装它,请在终端中输入以下命令。
pip install requests
方法一:在给定的 HTML 文档中查找类
方法思路
- 创建一个 HTML 文档。
- 导入所需模块。
- 将内容解析到 BeautifulSoup 对象中。
- 通过类名迭代或查找数据。
代码示例
Python3
# html 代码
html_doc = """Welcome to geeksforgeeks
Geeks
geeksforgeeks a computer science portal for geeks
"""
# 导入模块
from bs4 import BeautifulSoup
# 解析 html 内容
soup = BeautifulSoup( html_doc , ‘html.parser‘)
# 通过类名查找
soup.find( class_ = "body" )
输出结果
geeksforgeeks a computer science portal for geeks
方法二:编写程序查找 URL 中的所有类
方法思路
- 导入模块。
- 创建 requests 实例并传入 URL。
- 将请求结果传递给
Beautifulsoup()函数。 - 我们将遍历所有的标签并提取类名。
代码示例
Python3
# 导入模块
from bs4 import BeautifulSoup
import requests
# 网站 URL
URL = ‘https://www.geeksforgeeks.org/‘
# 类列表集合(使用集合避免重复)
class_list = set()
# 从网站 URL 获取页面内容
page = requests.get( URL )
# 解析 html 内容
soup = BeautifulSoup( page.content , ‘html.parser‘)
# 获取所有标签名称
tags = {tag.name for tag in soup.find_all()}
# 遍历所有标签
for tag in tags:
# 查找该标签的所有元素
for i in soup.find_all( tag ):
# 如果标签拥有 class 属性
if i.has_attr( "class" ):
if len( i[‘class‘] ) != 0:
class_list.add(" ".join( i[‘class‘]))
print( class_list )
输出结果
进阶实战:企业级类提取与 2026 开发范式
现在我们已经了解了基础用法。但在 2026 年,随着 Web 技术的飞速发展和开发理念的革新,仅仅这样写代码是不够的。让我们深入探讨如何在现代开发环境中优雅、高效地完成这个任务,并分享我们在生产环境中的实战经验。
生产级代码:健壮性与可维护性
你可能会发现,上面的基础代码在面对现代复杂的 Web 应用时会显得力不从心。网络波动、反爬虫机制、以及极其复杂的 HTML 结构都会导致脚本崩溃。在我们最近的一个大型数据迁移项目中,我们需要从数百万个遗留页面中提取样式类以重构 Design System。这迫使我们编写了一套更加健壮的解决方案。
让我们来看一个融合了 2026 年最佳实践的完整示例。我们将引入重试机制、超时处理以及更智能的解析策略。
Python 3.12+ 企业级示例
import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import time
def create_resilient_session(retries=3, backoff_factor=0.3):
"""
创建一个具有自动重试机制的 Session 对象。
这对于处理不稳定的网络环境或服务器的临时过载至关重要。
"""
session = requests.Session()
retry = Retry(
total=retries,
read=retries,
connect=retries,
backoff_factor=backoff_factor,
status_forcelist=(500, 502, 504)
)
adapter = HTTPAdapter(max_retries=retry)
session.mount(‘http://‘, adapter)
session.mount(‘https://‘, adapter)
return session
def extract_all_classes_modern(url):
"""
使用现代工程化方法提取 URL 中的所有类。
返回一个包含所有唯一类名的集合。
"""
unique_classes = set()
# 使用自定义的 Session
session = create_resilient_session()
try:
# 设置合理的 User-Agent,模拟真实浏览器行为
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36‘
}
# 发送请求,设置超时
response = session.get(url, headers=headers, timeout=10)
response.raise_for_status() # 检查 HTTP 错误
# 使用 lxml 解析器,通常比 html.parser 更快且容错性更强
# 如果环境限制,自动回退到 html.parser
soup = BeautifulSoup(response.content, ‘lxml‘)
# 直接迭代所有元素,而不是先获取标签名再查找,效率更高
for element in soup.find_all(True):
class_list = element.get(‘class‘)
if class_list:
# class 属性返回的是一个列表(即使 HTML 中是用空格分隔的字符串)
# 我们将它们重新组合并添加到集合中
unique_classes.update(class_list)
except requests.exceptions.RequestException as e:
print(f"网络请求出错: {e}")
except Exception as e:
print(f"解析过程中发生未预期的错误: {e}")
return unique_classes
# 让我们测试一下
target_url = ‘https://www.geeksforgeeks.org/‘
found_classes = extract_all_classes_modern(target_url)
print(f"共发现 {len(found_classes)} 个唯一的 CSS 类:")
for cls in sorted(found_classes):
print(cls)
深度解析与性能优化
你可能会问,为什么要这么麻烦?让我们思考一下这个场景:当你面对一个包含动态生成类名(如 Tailwind CSS 或 Styled Components 产生的哈希类名)的页面时,简单的脚本可能会因为解析速度过慢而显得不可用。
在上述代码中,我们做了几个关键的优化:
- 直接迭代:我们不再先构建一个 INLINECODE5889e659 集合再进行二次查找。INLINECODEcfd4bd23 可以直接遍历文档树中的所有节点,减少了 I/O 开销。
- 解析器选择:在 2026 年,INLINECODE4cb2d2fc 依然是高性能解析的首选。虽然 INLINECODE32800a03 是 Python 内置的,但在处理 malformed HTML(格式错误的 HTML)时,
lxml的容错性和速度都要好得多。 - 会话复用:使用 INLINECODEe460c6ce 而不是直接使用 INLINECODEa34fef9c,这允许 TCP 连接复用,显著减少建立连接的延迟。
常见陷阱与避坑指南
在我们多年的实战经验中,总结了一些新手(甚至是有经验的开发者)容易踩的坑。
1. class_ 参数的混淆
在调用 INLINECODE10e91c1f 或 INLINECODE49bd3f2f 时,INLINECODE23e726fc 是 Python 的保留字,因此 BeautifulSoup 要求我们使用 INLINECODEda74b2b2。
# 错误做法 (会报 SyntaxError)
soup.find(class="my-class")
# 正确做法
soup.find(class_="my-class")
2. 多类名的处理
这是最容易出错的地方。在 HTML 中,一个标签可以有多个类:
- INLINECODE4daaf141 返回的是列表:INLINECODE2319a2e9。
find(class_=‘btn‘)可以匹配到这个标签,因为它只要包含该类即可。- 但如果你试图通过精确匹配字符串 "btn btn-primary" 去查,可能会失败。使用
class_参数是最稳健的方式。
3. 嵌套与隐式闭合标签
BeautifulSoup 的强大之处在于它能修复破损的 HTML。但如果你在遍历树的同时修改树结构(例如 decompose()),很容易导致迭代器失效。最佳实践是先收集元素,再进行操作。
技术选型:何时不用 BeautifulSoup?
虽然 BeautifulSoup 是处理解析任务的瑞士军刀,但在 2026 年,我们的工具箱里还有其他选择。
- BeautifulSoup (bs4): 最适合 复杂的、格式错误的 HTML,以及需要快速迭代、原型开发的场景。它的容错率是最高的。
- lxml (仅 CSS 选择器): 如果你确信 HTML 是标准的(比如通过 API 获取的),且需要极致的性能,直接使用
lxml.html的 CSS 选择器会比 bs4 快数倍。 - Playwright / Selenium: 重要趋势。现在的网站越来越多地使用 JavaScript 渲染(CSR)。如果你的 INLINECODEc3926633 获取到的 HTML 里全是 INLINECODEe70669e0 而没有实际内容,那么纯 BS4 解决方案就失效了。你将需要使用无头浏览器来执行 JavaScript。
2026 开发新理念:AI 辅助的“氛围编程”
作为一个技术专家,我们不得不提到 Vibe Coding(氛围编程) 的兴起。在过去,我们需要死记硬背 BS4 的所有方法。但在 2026 年,我们更多地将 AI 视为我们的结对编程伙伴。
如何利用 AI 优化爬虫开发:
当我们面对一个从未见过的复杂网页结构时,我们可以利用 LLM(大语言模型)来辅助我们。
- 结构分析:我们可以将 HTML 结构粘贴给 AI,询问:“请帮我找出所有包含 ‘article‘ 关键词的 CSS 类,并生成对应的 BeautifulSoup 代码。”
- 数据清洗:提取出来的类名往往很乱(比如包含空格、换行符)。我们可以要求 AI 编写正则表达式来清洗这些数据。
- 代码解释与重构:如果你在维护老代码,可以将代码片段发给 AI,要求它“解释这段代码的逻辑,并按照 2026 年的异步标准进行重构”。
Agentic AI 工作流:甚至在更先进的场景下,我们可以构建一个自主 Agent。它接收 URL,自主判断是使用 INLINECODE7be7dbb8 + INLINECODE7c83b00e 还是 Playwright,自动处理反爬验证,并最终输出结构化的 JSON 数据。我们只需要定义目标,具体的实现细节由 Agent 动态生成。这就是未来的开发模式——从“写代码”转变为“定义意图”。
总结
在这篇文章中,我们不仅回顾了 BeautifulSoup 查找类的基础知识,更深入探讨了如何在 2026 年的技术背景下,编写生产级、高健壮性的爬虫代码。我们对比了不同的解析策略,分享了实战中的避坑指南,并展望了 AI 辅助编程的未来趋势。
无论你是刚入门的初学者,还是寻求优化的资深开发者,记住:工具是为了解决问题而存在的。在简单的任务中保持简单,在复杂的系统中拥抱现代工程化和 AI 辅助能力。现在,你可以尝试运行上面的代码,看看你能从你最喜欢的网站中提取出多少有趣的 CSS 类!