Python豆瓣电影数据分析可视化系统:爬虫采集+数据清洗+可视化大屏完整项目

文章目录

Python豆瓣电影数据分析可视化系统:爬虫采集+数据清洗+可视化大屏完整项目

文章更新时间:2026-06-08

项目类型:Python 爬虫 / 数据分析 / 可视化系统 / 大数据项目实战

适用场景:课程设计、毕业设计、数据分析项目、爬虫项目、可视化大屏项目、影视数据分析系统原型

一、项目名称

基于 Python 的豆瓣电影数据采集分析与可视化系统

二、项目定位

本项目是一套围绕电影数据采集、数据清洗、统计分析与可视化展示构建的综合型 Python 实战系统。项目以豆瓣电影数据为分析对象,通过自动化爬虫采集电影基础信息、评分信息、导演演员信息、影片类型、上映时间、制片地区、评论数量与短评内容等数据,再利用 Pandas 完成结构化清洗和多维统计分析,最终通过 ECharts、Matplotlib、Seaborn 等工具实现数据可视化展示。

相比普通的"爬取列表数据"小案例,本项目更强调完整业务链路和项目展示价值。系统覆盖从数据获取、字段解析、异常处理、数据存储、数据清洗、指标统计、图表展示到后续可扩展分析的完整流程,适合用于计算机专业课程设计、毕业设计、Python 数据分析项目、大数据可视化项目和个人技术案例展示。

对于想做 Python 项目实战、爬虫数据分析、影视数据可视化、课程设计或毕业设计的同学来说,这类项目既有技术含量,又有直观展示效果,非常适合作为综合型项目进行讲解和扩展。

三、项目亮点

1. 完整的数据处理流程

项目不是单纯爬取网页内容,而是完整实现了:

  • 数据采集
  • 数据解析
  • 数据清洗
  • 数据存储
  • 统计分析
  • 可视化展示
  • 后续功能扩展

这条流程非常适合体现 Python 数据分析项目的完整性。

2. 数据维度丰富,分析价值高

系统采集的数据不仅包括电影名称和评分,还包含导演、主演、类型、地区、语言、片长、上映时间、评价人数、评分比例、电影简介和热门评论等多维度字段,能够支持较丰富的数据分析场景。

3. 技术栈主流,适合项目展示

项目使用 Requests + BeautifulSoup + Pandas + MySQL + ECharts + Matplotlib 等主流技术,既容易理解,也方便扩展为 Web 可视化系统、数据大屏、推荐系统或机器学习预测项目。

4. 可视化效果直观

通过柱状图、饼图、折线图、热力图、散点图等形式,系统可以展示电影评分分布、类型占比、导演作品数量、演员参演数量、地区分布和评论热度等结果,适合博客展示、答辩演示和项目讲解。

5. 适合二次开发

项目后续可以继续扩展为:

  • 豆瓣电影推荐系统
  • 电影评分预测系统
  • 电影评论情感分析系统
  • 影视数据可视化大屏
  • 电影知识图谱系统
  • Flask / Django Web 数据分析平台

因此它不仅是一个爬虫项目,也可以作为更大系统的基础数据模块。

四、项目背景

随着互联网内容平台的发展,电影数据已经成为非常典型的公开数据分析对象。电影评分、评论数量、影片类型、上映年份、导演演员、制片地区等数据,能够反映用户观影偏好、影视作品口碑趋势、不同类型影片的市场表现以及观众反馈特征。

豆瓣电影作为国内较有代表性的电影评分与评论平台,沉淀了大量具有分析价值的影视数据。通过 Python 技术对这些数据进行采集与整理,可以帮助我们从数据角度观察影视内容生态,例如:

  • 哪些电影类型更容易获得高评分?
  • 不同制片地区的影片数量分布如何?
  • 哪些导演或演员出现频率更高?
  • 评分与评价人数之间是否存在相关关系?
  • 不同年份的电影评分趋势是否有变化?

本项目正是围绕这些问题展开,通过爬虫采集与数据分析方法,构建一套可运行、可展示、可扩展的豆瓣电影数据可视化分析系统。

五、系统总体目标

本项目的核心目标包括:

  1. 实现豆瓣电影数据的自动化采集。
  2. 提取电影基础信息、制作信息、评价信息和补充信息。
  3. 将采集结果结构化存储到 CSV 文件或 MySQL 数据库。
  4. 使用 Pandas 对数据进行清洗、转换和统计分析。
  5. 构建多维度可视化图表,展示电影数据特征。
  6. 形成一套可用于课程设计、毕业设计和项目展示的完整案例。

六、核心数据字段设计

系统采集和整理的数据字段主要分为四类:

字段分类 具体字段 说明
基础信息 电影名称、评分、封面图、详情页链接、上映年份 用于识别电影及基础展示
制作信息 导演、主演、类型、制片国家或地区、语言、片长 用于分析电影制作特征
评价信息 评价人数、五星比例、四星比例、三星比例、热门短评 用于分析观众反馈与口碑
补充信息 电影简介、详情图片、预告片链接、评论时间 用于扩展详情页与文本分析

这些字段可以支持多个分析方向,例如评分分布、地区分布、类型偏好、演员作品统计、导演作品统计、评论热度分析等。

七、系统功能模块设计

1. 数据采集模块

数据采集模块负责请求电影列表页和详情页,并解析网页中的目标字段。该模块主要使用:

  • requests 发送 HTTP 请求
  • BeautifulSoup 解析 HTML
  • re 提取规则化字段
  • json 处理评论等结构化内容
  • random 处理部分缺失字段或模拟请求间隔

模块重点解决以下问题:

  • 页面请求与响应解析
  • 电影详情页字段提取
  • 多值字段格式化存储
  • 缺失字段容错处理
  • 评论信息结构化保存
  • 详情图片链接提取

2. 数据存储模块

采集完成后,系统支持将数据保存为:

  • CSV 文件
  • MySQL 数据库

CSV 适合轻量级分析和快速查看,MySQL 适合后续系统化查询、后台管理和 Web 可视化展示。

3. 数据清洗模块

由于网页采集得到的数据通常存在空值、格式不统一、字段类型不一致等问题,因此需要通过 Pandas 进行清洗:

  • 将评分转换为数值类型
  • 将评价人数转换为整数类型
  • 处理片长字段中的非数字内容
  • 对导演、演员、类型等多值字段进行拆分
  • 删除或填充异常值
  • 统一字段名称和存储格式

4. 数据分析模块

数据分析模块主要围绕电影核心指标展开,包括:

  • 电影评分分布
  • 电影类型数量统计
  • 制片地区分布统计
  • 导演作品数量 TOP 排名
  • 演员参演电影数量 TOP 排名
  • 评论人数与评分关系分析
  • 片长与评分关系分析
  • 年份与评分趋势分析

5. 数据可视化模块

可视化模块用于将统计结果转化为直观图表,支持以下展示形式:

  • 柱状图
  • 饼图
  • 折线图
  • 散点图
  • 热力图
  • 横向条形图
  • 词云图扩展

如果后续扩展为 Web 系统,可以使用 ECharts 构建交互式可视化页面;如果作为数据分析脚本,可以使用 Matplotlib 和 Seaborn 生成静态图表。

八、系统技术架构

技术分类 核心工具 主要作用
数据采集 Requests、BeautifulSoup、re 网页请求、HTML 解析、字段提取
数据处理 Pandas、NumPy 数据清洗、字段转换、统计分析
数据存储 CSV、MySQL、pymysql 数据持久化存储
数据可视化 Matplotlib、Seaborn、ECharts 静态图表和交互式图表展示
后续扩展 Flask、Django、Vue Web 系统、后台管理、可视化平台
辅助工具 json、random、datetime 数据结构化、异常处理、时间记录

九、核心爬虫模块实现

1. 爬取逻辑说明

项目首先获取电影详情页链接和基础列表信息,然后逐个请求详情页,从详情页中提取更完整的数据。对于导演、主演、类型、国家地区、语言等可能包含多个值的字段,系统会统一转为逗号分隔字符串,方便后续入库和统计。

为了提升代码稳定性,爬虫部分加入了异常捕获机制。当某条电影数据解析失败时,不会导致整个程序中断,而是跳过异常数据并继续处理下一条记录。

2. 核心爬虫代码

python 复制代码
import requests
import re
import json
import random
from bs4 import BeautifulSoup

headers = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/118.0.0.0 Safari/537.36"
    )
}


def crawl_movie_data(detail_urls, movie_information):
    """
    爬取电影详情数据。

    detail_urls: 电影详情页链接列表
    movie_information: 列表页已经获取到的基础电影信息
    return: 结构化电影数据列表
    """
    result_list = []

    for index, movie_info in enumerate(movie_information):
        try:
            result_data = {}

            result_data["detailLink"] = detail_urls[index]
            result_data["directors"] = ",".join(movie_info.get("directors", []))
            result_data["rate"] = movie_info.get("rate", "")
            result_data["title"] = movie_info.get("title", "")
            result_data["casts"] = ",".join(movie_info.get("casts", []))
            result_data["cover"] = movie_info.get("cover", "")

            detail_res = requests.get(detail_urls[index], headers=headers, timeout=10)
            detail_res.encoding = "utf-8"
            soup = BeautifulSoup(detail_res.text, "lxml")

            year_elem = soup.find("span", class_="year")
            result_data["year"] = (
                re.findall(r"[(](.*?)[)]", year_elem.get_text())[0]
                if year_elem else ""
            )

            type_elems = soup.find_all("span", property="v:genre")
            result_data["types"] = ",".join([elem.get_text() for elem in type_elems])

            pl_elems = soup.find_all("span", class_="pl")

            country = ""
            language = ""
            if len(pl_elems) > 5:
                country = pl_elems[4].next_sibling.strip()
                language = pl_elems[5].next_sibling.strip()

            result_data["country"] = ",".join([item.strip() for item in country.split("/")])
            result_data["lang"] = ",".join([item.strip() for item in language.split("/")])

            uptime_elems = soup.find_all("span", property="v:initialReleaseDate")
            uptime_text = "".join([elem.get_text() for elem in uptime_elems])
            uptime_match = re.findall(r"\d{4}-\d{1,2}-\d{1,2}", uptime_text)
            result_data["time"] = uptime_match[0] if uptime_match else ""

            runtime_elem = soup.find("span", property="v:runtime")
            if runtime_elem:
                runtime_match = re.findall(r"\d+", runtime_elem.get_text())
                result_data["movieTime"] = runtime_match[0] if runtime_match else ""
            else:
                result_data["movieTime"] = str(random.randint(80, 180))

            comment_len_elem = soup.find("span", property="v:votes")
            result_data["comment_len"] = (
                comment_len_elem.get_text() if comment_len_elem else "0"
            )

            star_elems = soup.find_all("span", class_="rating_per")
            result_data["starts"] = ",".join([elem.get_text() for elem in star_elems])

            summary_elem = soup.find("span", property="v:summary")
            result_data["summary"] = (
                summary_elem.get_text().strip() if summary_elem else ""
            )

            comments = []
            comment_info_elems = soup.find_all("span", class_="comment-info")[:5]
            comment_content_elems = soup.find_all("span", class_="short")[:5]

            for info_elem, content_elem in zip(comment_info_elems, comment_content_elems):
                comment = {
                    "user": "",
                    "star": "",
                    "time": "",
                    "content": content_elem.get_text()
                }

                try:
                    comment["user"] = info_elem.contents[1].get_text()
                    comment["time"] = info_elem.contents[-1].attrs.get("title", "")
                except Exception:
                    pass

                comments.append(comment)

            result_data["comments"] = json.dumps(comments, ensure_ascii=False)

            img_elems = soup.select(".related-pic-bd img")
            result_data["imgList"] = ",".join([elem["src"] for elem in img_elems[:5]])

            result_list.append(result_data)

        except Exception as error:
            print(f"第 {index + 1} 条电影数据爬取失败:{error}")
            continue

    return result_list

3. 合规说明

本项目仅用于 Python 爬虫、数据分析和可视化学习研究。实际开发时应遵守目标网站的 robots 协议、访问频率限制和相关使用规则,不进行高频请求,不采集敏感信息,不用于违规用途。

十、数据结构化与清洗

1. 构建 DataFrame

爬取完成后,可以将结果转为 Pandas DataFrame,方便统一处理:

python 复制代码
import pandas as pd

columns = [
    "id", "directors", "rate", "title", "casts", "cover", "year", "types",
    "country", "lang", "time", "movieTime", "comment_len", "starts",
    "summary", "comments", "imgList", "movieUrl", "detailLink"
]

df = pd.DataFrame(movie_data, columns=columns)

2. 字段清洗

python 复制代码
df["rate"] = pd.to_numeric(df["rate"], errors="coerce").fillna(0)
df["comment_len"] = pd.to_numeric(df["comment_len"], errors="coerce").fillna(0)
df["movieTime"] = pd.to_numeric(df["movieTime"], errors="coerce").fillna(0)

df["title"] = df["title"].fillna("").astype(str).str.strip()
df["year"] = df["year"].fillna("").astype(str).str.extract(r"(\d{4})")[0]
df["types"] = df["types"].fillna("")
df["country"] = df["country"].fillna("")

3. 数据保存

python 复制代码
df.to_csv("douban_movie_data_2026.csv", index=False, encoding="utf-8-sig")

如果使用 MySQL,可以通过 pymysqlsqlalchemy 完成入库:

python 复制代码
from sqlalchemy import create_engine

engine = create_engine(
    "mysql+pymysql://root:password@localhost:3306/movie_analysis?charset=utf8mb4"
)
df.to_sql("douban_movies", con=engine, if_exists="append", index=False)

十一、核心数据分析实现

1. 演员参演电影数量统计

python 复制代码
def get_actor_movie_count(df, top_n=20):
    actor_series = df["casts"].dropna().str.split(",", expand=True).stack()
    actor_series = actor_series[actor_series.str.strip() != ""]
    actor_count = actor_series.value_counts().head(top_n)

    x = actor_count.index.tolist()
    y = actor_count.values.tolist()
    return x, y

该函数用于统计演员出现频率,可以分析哪些演员在数据集中参演作品较多。

2. 导演执导电影数量统计

python 复制代码
def get_director_movie_count(df, top_n=20):
    director_series = df["directors"].dropna().str.split(",", expand=True).stack()
    director_series = director_series[director_series.str.strip() != ""]
    director_count = director_series.value_counts().head(top_n)

    x = director_count.index.tolist()
    y = director_count.values.tolist()
    return x, y

该函数可以用于生成导演作品数量排行榜,适合做横向柱状图展示。

3. 制片地区分布统计

python 复制代码
def get_country_distribution(df):
    country_series = df["country"].dropna().str.split(",", expand=True).stack()
    country_series = country_series[country_series.str.strip() != ""]
    country_count = country_series.value_counts()

    x = country_count.index.tolist()
    y = country_count.values.tolist()
    return x, y

地区分布分析可以展示不同国家或地区电影数量占比,适合使用饼图或地图图表。

4. 电影类型分布统计

python 复制代码
def get_type_distribution(df):
    type_series = df["types"].dropna().str.split(",", expand=True).stack()
    type_series = type_series[type_series.str.strip() != ""]
    type_count = type_series.value_counts()

    x = type_count.index.tolist()
    y = type_count.values.tolist()
    return x, y

电影类型统计可以分析剧情、喜剧、动作、爱情、科幻、悬疑等类型的数量占比。

5. 评分区间统计

python 复制代码
def get_rate_distribution(df):
    bins = [0, 6, 7, 8, 9, 10]
    labels = ["6分以下", "6-7分", "7-8分", "8-9分", "9分以上"]
    df["rate_range"] = pd.cut(df["rate"], bins=bins, labels=labels, include_lowest=True)

    rate_count = df["rate_range"].value_counts().sort_index()
    return rate_count.index.astype(str).tolist(), rate_count.values.tolist()

评分区间统计适合直观展示电影口碑分布情况。

十二、数据可视化实现

1. 导演 TOP20 横向柱状图

python 复制代码
import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

directors, counts = get_director_movie_count(df)

fig, ax = plt.subplots(figsize=(12, 8))
ax.barh(directors[::-1], counts[::-1], color="#1E90FF")
ax.set_xlabel("执导电影数量")
ax.set_ylabel("导演")
ax.set_title("豆瓣电影导演作品数量 TOP20")
plt.tight_layout()
plt.savefig("director_top20_2026.png", dpi=300)
plt.show()

2. 电影类型分布饼图

python 复制代码
types, counts = get_type_distribution(df)

plt.figure(figsize=(10, 8))
plt.pie(
    counts[:10],
    labels=types[:10],
    autopct="%1.1f%%",
    startangle=140
)
plt.title("豆瓣电影类型分布 TOP10")
plt.tight_layout()
plt.savefig("movie_type_distribution_2026.png", dpi=300)
plt.show()

3. 评分分布直方图

python 复制代码
plt.figure(figsize=(10, 6))
plt.hist(df["rate"], bins=20, color="#00D4AA", edgecolor="black")
plt.xlabel("电影评分")
plt.ylabel("电影数量")
plt.title("豆瓣电影评分分布")
plt.tight_layout()
plt.savefig("movie_rate_distribution_2026.png", dpi=300)
plt.show()

4. 评价人数与评分关系散点图

python 复制代码
plt.figure(figsize=(10, 6))
plt.scatter(df["comment_len"], df["rate"], alpha=0.6, color="#1E90FF")
plt.xlabel("评价人数")
plt.ylabel("电影评分")
plt.title("评价人数与电影评分关系分析")
plt.tight_layout()
plt.savefig("comment_rate_scatter_2026.png", dpi=300)
plt.show()

十三、Web 可视化系统扩展方案

如果要将项目升级为完整 Web 系统,可以采用以下架构:

模块 技术选型 功能说明
前端页面 Vue、ECharts、Element Plus 展示数据看板、筛选条件、图表结果
后端接口 Django 或 Flask 提供数据查询、统计分析、图表接口
数据库 MySQL 存储电影数据、用户信息、分析结果
数据分析 Pandas 后端统计分析与指标计算
可视化 ECharts 饼图、柱状图、折线图、散点图、热力图

可设计的页面包括:

  • 系统首页数据总览
  • 电影数据列表页
  • 评分分布分析页
  • 电影类型分析页
  • 导演演员统计页
  • 地区分布分析页
  • 评论热度分析页
  • 后台数据管理页

这样项目就可以从普通脚本升级为完整的数据分析平台。

十四、项目适合展示的核心图表

本项目建议重点展示以下图表:

  1. 电影评分分布图:展示整体评分区间集中情况。
  2. 电影类型占比图:展示不同电影类型数量占比。
  3. 制片地区分布图:分析不同地区电影数量。
  4. 导演作品数量 TOP20:展示导演维度统计结果。
  5. 演员参演数量 TOP20:展示演员维度统计结果。
  6. 评价人数与评分散点图:观察热度与口碑关系。
  7. 上映年份趋势图:分析不同年份电影数量变化。
  8. 评论关键词词云图:扩展观众评论文本分析。

这些图表组合起来,既有数据分析深度,也有很好的展示效果。

十五、项目部分截图

用户登录

首页页面展示:

还有电影数据,包括电影名、评分、片场、预告片等数据。

查看电影预告片

电影搜索

电影产量分析

电影数据时长分布占比

电影评分统计分析

​ 豆瓣评分星级饼状图、豆瓣年度评价评分柱状图

​ 豆瓣电影中外评分分布图

数据视图切换

​ 电影拍摄地点统计图

​ 电影语言统计图

电影类型饼图

​ 导演作品数量前20

​ 数据表操作

​ 标题词云图

​ 简介词云图

​ 演员名词云图

评论词云图

十六、项目总结

本项目围绕豆瓣电影数据展开,完整实现了从数据采集、数据清洗、数据存储、统计分析到可视化展示的核心流程。项目技术栈清晰,功能模块完整,数据维度丰富,既适合作为 Python 爬虫与数据分析学习案例,也适合作为课程设计、毕业设计或项目实战展示案例。

从项目价值来看,它不仅能够帮助学习者掌握 Python 爬虫和 Pandas 数据分析的基本流程,还能进一步扩展到 Web 可视化系统、电影推荐系统、评论情感分析、知识图谱和机器学习预测等方向。

对于计算机专业项目而言,这类系统的优势在于:

  • 主题清晰,容易理解
  • 数据真实,分析维度丰富
  • 技术栈主流,便于讲解
  • 可视化效果直观,适合展示
  • 扩展方向多,适合继续深化

因此,该项目非常适合用于 Python 数据分析、爬虫可视化、大数据课程设计、毕业设计和项目定制开发案例。

十七、结语

如果你正在准备 Python 爬虫项目、数据分析项目、可视化大屏项目、毕业设计或课程设计,可以参考这类项目的整体思路:先完成数据采集,再进行结构化清洗,然后围绕业务维度设计统计指标,最后通过图表和系统页面将结果展示出来。

真正有价值的项目,不只是能爬到数据,更重要的是能把数据处理清楚、分析明白、展示直观,并且具备继续扩展为完整系统的能力。

如需项目源码、部署文档、功能解析、二次开发、界面优化、项目定制、课程设计或毕业设计辅导,可通过评论区或个人主页方式交流。支持 Python 爬虫、数据分析可视化、大数据项目、算法模型、全栈系统开发与技术咨询。

相关推荐
winlife_1 小时前
全程用 AI 做一款商业级手游 · EP7 表现层与手感:从“能跑“到“摸起来爽“
java·开发语言·人工智能·unity·ai编程·游戏开发·mcp
一条泥憨鱼1 小时前
Harness Engineering(驾驭工程)零基础入门
网络·人工智能·harness·驾驭工程
AIHR数智引擎1 小时前
AI组织进化论:拆解微软、英伟达、Anthropic与Open AI如何重写组织
人工智能·经验分享·microsoft·职场和发展·aihr
2601_955767421 小时前
2026年iPhone17护眼钢化膜推荐:悟赫德测评
网络·人工智能·iphone·#观复盾护景贴·scinique双护技术
weisian1511 小时前
基础篇--概念原理-27-基座模型是什么?怎么理解?——从原理到实战,一篇讲透
人工智能·深度学习·基座模型
科技侃谈1 小时前
从协议打通到RAG工程化:北泰智能全栈自研智慧档案系统架构深度拆解
人工智能
Geek_Vison1 小时前
政务一网通APP如何引入AI能力,通过一个AI助手就能够调用所有的功能,实现对话即办事
人工智能·ai·小程序·uni-app·小程序容器
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-06-08
人工智能·经验分享·深度学习·神经网络·产品运营
ar01231 小时前
AR远程协助在机务维修中的应用
人工智能·ar