什么是 Beautiful Soup?
Beautiful Soup 是一个 Python 库,它的主要功能是解析和遍历 HTML/XML 文档,并提供一种简单、符合人类直觉的方式来导航、搜索和修改解析树。

它的作用就是:
- 接收一个 HTML/XML 文档(字符串或文件句柄)。
- 解析它,将其转换成一个复杂的树形结构(我们称之为“解析树”或“Soup 对象”)。
- 提供一套简单的方法,让你可以方便地在这个树中查找、定位和提取你想要的数据。
为什么选择 Beautiful Soup?
直接用 Python 的字符串处理方法(如 split(), find(), replace())来解析 HTML 是非常痛苦且低效的,因为 HTML 结构复杂,标签嵌套、属性多变。
Beautiful Soup 的优势在于:
- 容错性强:它能很好地处理不规范的、甚至有错误的 HTML 代码,这是它最强大的特点之一。
- API 简单易用:提供了非常直观的 API,学习成本低,上手快。
- 功能强大:支持多种解析器,并且提供了强大的搜索方法(如
find(),find_all())。 - 文档完善:官方文档非常详细,有大量的例子和教程。
安装与基本使用
1 安装
你需要安装 Beautiful Soup 库,强烈建议你安装一个解析器,lxml,它的速度和容错性都很好。

# 安装 beautifulsoup4 库本身 pip install beautifulsoup4 # 安装一个高效的解析器 (推荐) pip install lxml # 也可以使用 Python 内置的 html.parser # pip install html5lib # 另一个容错性极强的解析器
2 基本使用流程
Beautiful Soup 的使用通常遵循以下三步:
- 导入库:
from bs4 import BeautifulSoup - 创建 Soup 对象:将网页源代码(字符串)或文件传递给
BeautifulSoup构造函数。 - 查找和提取数据:使用 Soup 对象的方法(如
.find(),.find_all(),.select()等)来定位元素。
核心概念与方法
假设我们有下面这段 HTML 代码作为示例:
html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """
1 创建 Soup 对象
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc, 'lxml') # 使用 lxml 解析器
2 导航和查找
Beautiful Soup 提供了两种主要的查找方式:
A. 树形导航 (.find() 和 .find_all())

这是最核心、最常用的方法。
.find(name, attrs, recursive, ...):查找第一个匹配的元素。.find_all(name, attrs, recursive, ...):查找所有匹配的元素,返回一个列表。
示例:
# 1. 查找标签名
# 查找第一个 <a> 标签
first_a_tag = soup.find('a')
print(f"第一个 a 标签: {first_a_tag}")
# 输出: 第一个 a 标签: <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
# 查找所有的 <a> 标签
all_a_tags = soup.find_all('a')
print(f"\n所有的 a 标签: {all_a_tags}")
# 输出: 所有的 a 标签: [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, ...]
# 2. 使用属性查找
# 查找 id 为 "link2" 的标签
link2 = soup.find(id='link2')
print(f"\nID 为 link2 的标签: {link2}")
# 输出: ID 为 link2 的标签: <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
# 查找 class 为 "sister" 的所有标签 (注意:class 是 Python 的保留字,所以用 class_)
sister_tags = soup.find_all(class_='sister')
print(f"\nClass 为 sister 的所有标签: {sister_tags}")
# 3. 组合查找
# 查找所有 <a> 标签,class 是 "sister"
a_sisters = soup.find_all('a', class_='sister')
print(f"\n所有 a 标签且 class 为 sister: {a_sisters}")
# 查找所有 <p> 标签,class 是 "story"
p_stories = soup.find_all('p', class_='story')
print(f"\n所有 p 标签且 class 为 story: {p_stories}")
B. CSS 选择器 (.select() 和 .select_one())
如果你熟悉 CSS 选择器,这种方式会更加灵活和强大。
.select(css_selector):查找所有匹配 CSS 选择器的元素,返回一个列表。.select_one(css_selector):查找第一个匹配 CSS 选择器的元素。
示例:
# 1. 通过标签名选择
p_tags = soup.select('p')
print(f"所有 p 标签: {p_tags}")
# 2. 通过类名选择 (加点 .)class = soup.select('.title')
print(f"\nClass 为 title 的标签: {title_class}")
# 3. 通过 ID 选择 (加井号 #)
link1_id = soup.select('#link1')
print(f"\nID 为 link1 的标签: {link1_id}")
# 4. 组合选择 (后代选择器)
# 查找 body 内部的所有 a 标签
body_a_tags = soup.select('body a')
print(f"\nbody 内部的所有 a 标签: {body_a_tags}")
# 5. 属性选择 (用方括号 [])
# 查找所有 href 属性包含 "example.com" 的 a 标签
href_example = soup.select('a[href*="example.com"]')
print(f"\nhref 包含 example.com 的 a 标签: {href_example}")
3 提取信息
找到元素后,下一步就是提取我们关心的信息:文本、链接、图片地址等。
# 假设我们已经找到了一个标签
a_tag = soup.find('a', id='link1')
# 1. 获取文本内容
# .string: 如果标签内只有一个字符串,返回该字符串
# .text: 获取标签内所有内容(包括子孙标签的文本),并拼接成一个字符串
# .get_text(): 和 .text 类似,但更灵活,可以控制分隔符等
name = a_tag.string
print(f"标签内的文本: {name}") # 输出: Elsie
all_text_in_p = soup.find('p', class_='story').text
print(f"story p 标签内的所有文本: {all_text_in_p}")
# 2. 获取属性值
# 直接像字典一样访问,或使用 .get() 方法
href = a_tag['href']
# 或者
href_get = a_tag.get('href')
print(f"链接地址: {href}") # 输出: http://example.com/elsie
# 获取 class 属性 (返回的是一个列表)
class_list = a_tag['class']
print(f"Class 属性列表: {class_list}") # 输出: ['sister']
完整实例:抓取网页标题和所有链接
下面是一个完整的例子,展示如何抓取一个网页的标题和所有链接。
import requests
from bs4 import BeautifulSoup
# 1. 获取网页内容
url = 'http://quotes.toscrape.com/' # 一个用来练习的网站
try:
response = requests.get(url)
response.raise_for_status() # 如果请求失败 ( 