上篇文章介绍了 XPath 解析网页,本文继续讲解另一种常用的解析方式——BeautifulSoup4(简称 BS4),并用豆瓣 Top250 作为实战案例,对比两种方式的优劣。
一、BeautifulSoup 是什么
BeautifulSoup 是一个 Python 库,用于从 HTML/XML 文档中提取数据。它通过将网页解析为标签树结构,提供更直观的方式来查找和提取元素。
安装
pip install beautifulsoup4 lxml
基本用法
from bs4 import BeautifulSoup
import requests
# 获取网页
resp = requests.get("https://example.com")
resp.encoding = "utf-8"
# 解析为 BS4 对象
soup = BeautifulSoup(resp.text, "lxml")
# 提取数据
print(soup.title.text) # 页面标题
print(soup.find("h1").text) # 查找第一个 h1
print(soup.select(".content")) # CSS 选择器
二、BS4 核心用法速查
1. 查找标签
soup.find("div") # 查找第一个 div
soup.find_all("a") # 查找所有 a 标签,返回列表
soup.find(id="content") # 按 id 查找
soup.find(class_="title") # 按 class 查找(注意 class_ 有下划线)
2. CSS 选择器(最常用)
soup.select("div") # 所有 div
soup.select(".title") # class="title" 的元素
soup.select("#content") # id="content" 的元素
soup.select("div > p") # div 的直接子元素 p
soup.select("div p") # div 下的所有 p
soup.select("li[class=item]") # 按属性筛选
3. 提取数据
tag.text # 获取标签内的文本
tag.get("href") # 获取属性值(安全,不存在返回 None)
tag["href"] # 直接获取属性(不存在会报错)
tag.name # 标签名
三、实战:爬取豆瓣电影 Top250
跟上篇 XPath 文章一样的目标——抓取排名、片名、评分和评价人数,方便对比两种方式的差异。
单页爬取
from bs4 import BeautifulSoup
import requests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
def crawl_douban_bs4():
url = "https://movie.douban.com/top250"
resp = requests.get(url, headers=headers)
resp.encoding = "utf-8"
soup = BeautifulSoup(resp.text, "lxml")
# CSS 选择器定位所有电影项
items = soup.select("ol.grid_view li")
for item in items:
# 排名
rank = item.select_one("em").text
# 片名(取第一个 .title 即中文名)
title = item.select_one("span.title").text
# 评分
rating = item.select_one("span.rating_num").text
# 评价人数:找包含"人评价"的 span
people = ""
for tag in item.select("div.bd span"):
if "人评价" in tag.text:
people = tag.text.strip()
break
print(f"{rank:>3}. {title} ⭐{rating} {people}")
resp.close()
crawl_douban_bs4()
输出效果:
1. 肖申克的救赎 ⭐9.7 3294764人评价
2. 霸王别姬 ⭐9.6 2202234人评价
3. 泰坦尼克号 ⭐9.4 2222751人评价
…
分页爬取(10页全部)
豆瓣 Top250 一共 10 页,URL 规律是 ?start=0、?start=25 … ?start=225:
def crawl_all_pages():
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
all_movies = []
for page in range(10):
start = page * 25
url = f"https://movie.douban.com/top250?start={start}"
resp = requests.get(url, headers=headers)
resp.encoding = "utf-8"
soup = BeautifulSoup(resp.text, "lxml")
items = soup.select("ol.grid_view li")
for item in items:
people = ""
for tag in item.select("div.bd span"):
if "人评价" in tag.text:
people = tag.text.strip()
break
movie = {
"rank": item.select_one("em").text,
"title": item.select_one("span.title").text,
"rating": item.select_one("span.rating_num").text,
"people": people
}
all_movies.append(movie)
print(f"第 {page+1} 页完成,已爬取 {len(all_movies)} 条")
print(f"\\n共爬取 {len(all_movies)} 部电影")
return all_movies
movies = crawl_all_pages()
四、XPath vs BeautifulSoup 实战对比
以豆瓣 Top250 爬取为例,对比两种方式:
| 解析速度 | 快 | 稍慢 |
| 定位排名 | //em/text() | item.select_one("em").text |
| 定位片名 | //span[@class="title"]/text() | item.select_one("span.title").text |
| 定位评分 | //span[@class="rating_num"]/text() | item.select_one("span.rating_num").text |
| 定位评价人数 | //span[contains(text(), "人评价")]/text() | 遍历 + if "人评价" in tag.text |
| 代码可读性 | 表达式简洁 | 方法链更直观 |
| 学习门槛 | 需要学 XPath 语法 | 接近直觉,上手快 |
结论
- 大规模爬虫(千页以上)→ XPath 速度优势明显
- 快速开发(几十页)→ BS4 更顺手
- 推荐组合:两个都学,哪个方便用哪个
五、BS4 踩坑提醒
class 参数注意下划线:
# 正确
soup.find(class_="title")
# 错误(class 是 Python 关键字)
soup.find(class="title")
text 属性 vs string 属性:
- tag.text — 获取标签及其所有子标签的文本(递归)
- tag.string — 只获取标签本身的文本
CSS 选择器中的空格含义:
soup.select("div span") # div 下的所有 span(后代)
soup.select("div > span") # div 的直接子 span
不要用 find_all 的 text= 参数(已废弃,直接用循环判断)
总结
BeautifulSoup4 是 Python 爬虫入门的最佳解析库之一,语法直观,配合 CSS 选择器可以快速提取页面数据。建议初学者优先掌握 BS4,再深入学习 XPath 提升解析效率。
两篇文章的完整代码可以在我的 CSDN 资源中下载。
如果对你有帮助,欢迎点赞、评论、关注【张老师技术栈】,持续分享 Java/Python/爬虫 实战干货。



