欢迎光临
我们一直在努力

BeautifulSoup4实战:爬取豆瓣电影Top250(附完整代码)

上篇文章介绍了 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 爬取为例,对比两种方式:

对比项XPath(lxml)BeautifulSoup
解析速度 稍慢
定位排名 //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/爬虫 实战干货。

    赞(0)
    未经允许不得转载:171主机测评 » BeautifulSoup4实战:爬取豆瓣电影Top250(附完整代码)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址