不用复杂框架!30行Python爬豆瓣TOP250电影,新手也能跑通+数据可视化分析(附完整代码)

最近想整理一份「周末宅家必看高分电影清单」,翻豆瓣TOP250一页页复制电影名、评分、年份,手都酸了——作为程序员,这种重复活当然得用代码解决!这篇就带刚入门爬虫的朋友一步步实操:不用Scrapy这些复杂框架,只用requests+BeautifulSoup,30行核心代码爬完所有数据,最后还能画图表分析高分电影的规律,全程无门槛,看完跟着敲就能跑通。

一、先搞懂:爬豆瓣TOP250需要解决哪些小问题?

新手写爬虫最容易卡壳的不是代码本身,而是没搞懂「网页怎么结构」「怎么不被网站拒绝」。先梳理下核心需求:

爬什么数据:电影名称、评分、上映年份、导演、评价人数(这些是做清单最有用的信息);怎么爬多页:豆瓣TOP250分10页,每页25部,URL里的
start
参数从0到225(每次加25);怎么不被封:至少加个「请求头」模拟浏览器,不然豆瓣会直接返回403拒绝访问;数据怎么用:存成CSV方便后续看,再用图表分析下高分电影的年份分布、评分规律,比单纯爬数据有意思。

二、环境准备: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"
旁边的
span
(比如「123456人评价」)。

简单说:每部电影对应一个
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. 新手必看:避坑指南

为什么加请求头? 豆瓣会识别请求来源,如果没加
User-Agent
,会认为是爬虫,直接返回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能解决这个问题。

四、数据可视化:让高分电影规律“看得见”

光爬数据没意思,我们用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
属性,用
requests
下载图片,存到本地文件夹;分析导演作品:统计哪些导演的作品入选最多(比如宫崎骏、诺兰、斯皮尔伯格),画个条形图;爬取短评:进入每部电影的详情页,爬取前100条短评,分析观众对“神片”的评价关键词(需要用到词云库
wordcloud
)。

六、最后说句大实话

爬虫入门不难,难的是“敢动手”——很多新手总担心“被封IP”“搞坏网站”,其实像豆瓣TOP250这种公开数据,只要控制好请求频率(比如每页间隔1秒,代码里加
time.sleep(1)
),加好请求头,完全没问题。

这篇的代码我自己跑过好几遍,新手跟着敲,遇到报错别慌:比如请求超时就检查网络,解析不到数据就重新看网页结构(豆瓣偶尔会改HTML,要重新确认标签)。爬完数据再画个图,看着自己整理的高分电影清单,成就感拉满~

如果爬的时候遇到问题,评论区可以留言,咱们一起解决!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
pillsnfiction的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容