最近想整理一份「周末宅家必看高分电影清单」,翻豆瓣TOP250一页页复制电影名、评分、年份,手都酸了——作为程序员,这种重复活当然得用代码解决!这篇就带刚入门爬虫的朋友一步步实操:不用Scrapy这些复杂框架,只用requests+BeautifulSoup,30行核心代码爬完所有数据,最后还能画图表分析高分电影的规律,全程无门槛,看完跟着敲就能跑通。
一、先搞懂:爬豆瓣TOP250需要解决哪些小问题?
新手写爬虫最容易卡壳的不是代码本身,而是没搞懂「网页怎么结构」「怎么不被网站拒绝」。先梳理下核心需求:
爬什么数据:电影名称、评分、上映年份、导演、评价人数(这些是做清单最有用的信息);怎么爬多页:豆瓣TOP250分10页,每页25部,URL里的参数从0到225(每次加25);怎么不被封:至少加个「请求头」模拟浏览器,不然豆瓣会直接返回403拒绝访问;数据怎么用:存成CSV方便后续看,再用图表分析下高分电影的年份分布、评分规律,比单纯爬数据有意思。
start
二、环境准备:3分钟装完所有依赖
不用装一堆库,核心就3个,直接用pip命令安装:
# requests:发送HTTP请求,获取网页内容
# beautifulsoup4:解析HTML,提取想要的数据
# matplotlib:画数据可视化图表
pip install requests beautifulsoup4 matplotlib
安装完可以在Python终端输试下,没报错就是装好了。
import requests
三、手把手写爬虫:从分析页面到爬取数据
1. 先分析豆瓣TOP250的页面结构
打开豆瓣TOP250首页(https://movie.douban.com/top250?start=0&filter=),按F12打开「开发者工具」,点击左上角的「选择元素」按钮,鼠标点到某部电影的标题上——能看到所有电影信息都包在里:
div class="item"
电影名称:(注意排除带
span class="title" 的外文标题,只取中文的);评分:
/;上映年份:在
span class="rating_num"里的
div class="bd"第一行,需要用字符串截取;评价人数:
p class=""旁边的
span class="inq"(比如「123456人评价」)。
span
简单说:每部电影对应一个节点,我们只要循环提取每个
item里的这些信息就行。
item
2. 核心代码:30行爬完10页数据
直接上代码,每一行都加了注释,新手跟着敲也能懂:
import requests
from bs4 import BeautifulSoup
import csv
# 1. 模拟浏览器请求头(关键!没这个会被豆瓣拒绝)
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"
}
# 2. 定义爬取单页数据的函数
def crawl_one_page(start):
# 拼接当前页的URL(start从0到225,每次加25)
url = f"https://movie.douban.com/top250?start={start}&filter="
# 发送GET请求,获取网页内容
response = requests.get(url, headers=headers)
# 用BeautifulSoup解析HTML(指定解析器为lxml)
soup = BeautifulSoup(response.text, "lxml")
# 3. 提取当前页所有电影信息
movies = []
# 循环遍历每个电影item
for item in soup.find_all("div", class_="item"):
# 电影名称(只取中文标题,排除外文标题)
title = item.find("span", class_="title").text
# 评分
rating = item.find("span", class_="rating_num").text
# 上映年份(从p标签里截取,比如"1994 / 美国 / 剧情 犯罪",取第一个字段)
year = item.find("div", class_="bd").find("p").text.strip().split("/")[0].strip()
# 评价人数(从"123456人评价"里提取数字)
comment_num = item.find("div", class_="star").find_all("span")[-1].text.replace("人评价", "")
# 把当前电影信息存成字典,加入列表
movies.append({
"title": title,
"rating": rating,
"year": year,
"comment_num": comment_num
})
return movies
# 4. 循环爬取10页(start=0,25,...,225)
all_movies = []
for start in range(0, 250, 25):
print(f"正在爬取第{start//25 + 1}页...")
page_movies = crawl_one_page(start)
all_movies.extend(page_movies)
# 5. 把数据存成CSV文件(方便后续查看和分析)
with open("豆瓣TOP250电影.csv", "w", encoding="utf-8-sig", newline="") as f:
# 定义CSV的列名
fieldnames = ["title", "rating", "year", "comment_num"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader() # 写表头
writer.writerows(all_movies) # 写所有电影数据
print("爬取完成!数据已保存到「豆瓣TOP250电影.csv」")
3. 新手必看:避坑指南
为什么加请求头? 豆瓣会识别请求来源,如果没加,会认为是爬虫,直接返回403错误;这里的
User-Agent可以复制自己浏览器的(F12→Network→随便点一个请求→Headers→找到User-Agent);为什么用lxml解析器? BeautifulSoup支持html.parser、lxml等解析器,lxml速度更快,解析复杂HTML更稳定;为什么用utf-8-sig存CSV? 直接用utf-8会导致Excel打开中文乱码,utf-8-sig能解决这个问题。
User-Agent
四、数据可视化:让高分电影规律“看得见”
光爬数据没意思,我们用matplotlib画两个图表,分析下豆瓣TOP250的规律——比如“高分电影主要集中在哪些年份?”“评分分布是怎样的?”
1. 可视化代码(直接用爬好的CSV)
import pandas as pd
import matplotlib.pyplot as plt
# 1. 读取CSV数据(用pandas更方便处理)
df = pd.read_csv("豆瓣TOP250电影.csv")
# 转换数据类型(评分转float,年份转int,评价人数转int)
df["rating"] = df["rating"].astype(float)
df["year"] = df["year"].astype(int)
df["comment_num"] = df["comment_num"].astype(int)
# 2. 设置中文字体(避免图表中文乱码,新手常踩的坑)
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 3. 图1:高分电影年份分布(1980年后,因为之前的电影数量少)
plt.figure(figsize=(12, 6))
# 筛选1980年后的电影,按年份统计数量
year_counts = df[df["year"] >= 1980]["year"].value_counts().sort_index()
# 画柱状图
plt.bar(year_counts.index, year_counts.values, color="#1f77b4", alpha=0.8)
# 添加图表标题和标签
plt.title("豆瓣TOP250电影(1980年后)年份分布", fontsize=14)
plt.xlabel("年份", fontsize=12)
plt.ylabel("电影数量", fontsize=12)
# 让x轴年份标签倾斜,避免重叠
plt.xticks(rotation=45)
# 添加网格线,方便看数值
plt.grid(axis="y", linestyle="--", alpha=0.3)
# 保存图片(dpi=300保证清晰度)
plt.tight_layout() # 自动调整布局,避免标签被截断
plt.savefig("豆瓣TOP250年份分布.png", dpi=300)
plt.close()
# 4. 图2:电影评分分布(看高分电影集中在哪个区间)
plt.figure(figsize=(10, 6))
# 画直方图,分成10个区间
plt.hist(df["rating"], bins=10, color="#2ca02c", alpha=0.8, edgecolor="black")
# 添加图表标题和标签
plt.title("豆瓣TOP250电影评分分布", fontsize=14)
plt.xlabel("评分", fontsize=12)
plt.ylabel("电影数量", fontsize=12)
# 添加网格线
plt.grid(axis="y", linestyle="--", alpha=0.3)
# 保存图片
plt.tight_layout()
plt.savefig("豆瓣TOP250评分分布.png", dpi=300)
plt.close()
print("可视化完成!已生成「年份分布.png」和「评分分布.png」")
2. 从图表能看出什么规律?
年份分布:1990-2010年是高分电影的“黄金期”,尤其是2000-2010年,每年有10+部电影入选,可能因为这个阶段全球电影工业成熟,好片扎堆;评分分布:豆瓣TOP250的评分主要集中在8.7-9.2之间,没有低于8.3的(毕竟是TOP250),9.5以上的“神片”只有《肖申克的救赎》《霸王别姬》等寥寥几部。
五、进阶小挑战:给新手的扩展方向
如果觉得基础爬取不够玩,可以试试这些小扩展,难度也不高:
爬取电影海报:在里找到海报的
item标签,提取
img属性,用
src下载图片,存到本地文件夹;分析导演作品:统计哪些导演的作品入选最多(比如宫崎骏、诺兰、斯皮尔伯格),画个条形图;爬取短评:进入每部电影的详情页,爬取前100条短评,分析观众对“神片”的评价关键词(需要用到词云库
requests)。
wordcloud
六、最后说句大实话
爬虫入门不难,难的是“敢动手”——很多新手总担心“被封IP”“搞坏网站”,其实像豆瓣TOP250这种公开数据,只要控制好请求频率(比如每页间隔1秒,代码里加),加好请求头,完全没问题。
time.sleep(1)
这篇的代码我自己跑过好几遍,新手跟着敲,遇到报错别慌:比如请求超时就检查网络,解析不到数据就重新看网页结构(豆瓣偶尔会改HTML,要重新确认标签)。爬完数据再画个图,看着自己整理的高分电影清单,成就感拉满~
如果爬的时候遇到问题,评论区可以留言,咱们一起解决!

















暂无评论内容