用 Python Flask 从零重构“电视剧趣推系统”——Web 版推荐引擎

本文将此前的 Java 控制台推荐系统项目重构为 Web 版,使用 Python + Flask 从零搭建一个可浏览器访问的“电视剧趣推系统”。项目不依赖数据库,采用纯内存数据模型,适合 Python 初学者和 Web 开发入门者学习。

系统包含电视剧展示、用户偏好记录、智能推荐三大核心功能。后端基于 Flask 实现路由控制与推荐逻辑,前端使用 Jinja2 模板引擎结合 Bootstrap 快速构建响应式页面,实现“喜欢”操作与个性化推荐。推荐策略采用“偏好类型匹配 + 高分优先”算法,为用户生成定制化内容。

文章提供完整项目结构、逐行代码解析、HTML 模板设计、运行教程及常见问题解决方案。项目结构清晰、注释详尽、扩展性强,支持后续接入 SQLite、用户登录、REST API 等进阶功能。

通过本项目,读者可掌握 Flask 基础开发流程、前后端数据传递、模板渲染、session 管理等核心技能,是 Python Web 入门的优质练手项目。

关键词:Python Flask、推荐系统、Web 开发、Jinja2、Bootstrap、零基础入门、CSDN 教程

🌟 前言

还记得我们之前用 Java 写的“电视剧趣推系统”吗?👉 回顾文章

今天,我们要把它升级为 Web 版!使用 Python + Flask + HTML 模板,打造一个可以在浏览器中访问的推荐系统!

🎯 本项目目标:

  • ✅ 将 Java 控制台程序转为 Web 应用
  • ✅ 使用 Flask 构建后端 API 与页面路由
  • ✅ 用 Jinja2 模板渲染前端页面
  • ✅ 实现用户喜欢、智能推荐、数据管理功能
  • ✅ 零数据库依赖,纯内存存储(后续可扩展为 SQLite)

📌 适合人群:Python 入门者、想学 Web 开发的新手、对推荐系统感兴趣的同学。


🧱 一、项目功能概览

功能说明
📺 浏览所有剧集在网页上查看电视剧列表
❤️ 点击“喜欢”按钮用户可标记喜欢的剧
🔮 智能推荐根据用户偏好推荐同类高分剧
👤 用户切换支持多个用户,记住各自喜好
🖥️ Web 界面Bootstrap 美化,响应式布局

技术栈

  • Flask:轻量级 Web 框架
  • Jinja2:HTML 模板引擎
  • Bootstrap:前端样式库
  • session:用户状态管理

🗂️ 二、项目目录结构

tv_recommender/
├── app.py                  → Flask 主程序
├── templates/              → HTML 页面模板
│   ├── base.html           → 布局母版
│   ├── index.html          → 首页(浏览+喜欢)
│   ├── recommend.html      → 推荐页
│   └── users.html          → 用户管理页
├── static/
│   └── style.css           → 自定义样式(可选)
└── data.py                 → 模拟数据初始化(可选分离)

💡 提示:Flask 默认会从 templates/ 找 HTML,从 static/ 找 CSS/JS。


💻 三、环境准备

1. 安装 Python(建议 3.7+)

python --version

2. 安装 Flask

pip install flask

✅ 验证安装:

python -c "from flask import Flask; print('Flask installed!')"

🧩 四、核心数据模型设计(Python 类)

我们先定义两个类:TVShowUser,对应 Java 中的实体。

TVShow 类 —— 电视剧

# tv_show.py (或直接写在 app.py 中)
class TVShow:
    def __init__(self, show_id, title, genre, rating, description):
        self.id = show_id
        self.title = title
        self.genre = genre
        self.rating = rating
        self.description = description

    def __repr__(self):
        return f"<TVShow {self.title}>"

    def to_dict(self):
        """方便传递给前端"""
        return {
            'id': self.id,
            'title': self.title,
            'genre': self.genre,
            'rating': self.rating,
            'description': self.description
        }

User 类 —— 用户

class User:
    def __init__(self, user_id, name):
        self.id = user_id
        self.name = name
        self.liked_show_ids = set()  # 用 set 防止重复

    def like(self, show_id):
        self.liked_show_ids.add(show_id)

    def has_liked(self, show_id):
        return show_id in self.liked_show_ids

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'liked_count': len(self.liked_show_ids)
        }

⚙️ 五、推荐引擎逻辑(核心算法)

def get_recommendations(user, all_shows, all_users):
    """
    为用户生成推荐列表
    """
    if user is None or not user.liked_show_ids:
        # 用户未登录或未喜欢任何剧 → 推荐全局高分TOP5
        return sorted(all_shows.values(), key=lambda x: x.rating, reverse=True)[:5]

    # 统计用户最喜欢哪种类型
    genre_count = {}
    for show_id in user.liked_show_ids:
        show = all_shows.get(show_id)
        if show:
            genre = show.genre
            genre_count[genre] = genre_count.get(genre, 0) + 1

    # 找出最喜欢的类型
    favorite_genre = max(genre_count, key=genre_count.get) if genre_count else "Drama"

    # 推荐该类型中评分高且未被喜欢的剧
    recommendations = []
    for show in all_shows.values():
        if show.genre == favorite_genre and show.id not in user.liked_show_ids:
            recommendations.append(show)

    # 按评分排序,取前5部
    recommendations.sort(key=lambda x: x.rating, reverse=True)
    return recommendations[:5]

🧠 逻辑解析

  • 若无偏好 → 推高分剧
  • 有偏好 → 统计类型频次 → 推同类未看高分剧

🖥️ 六、Flask 主程序 —— app.py

from flask import Flask, render_template, request, redirect, url_for, session
import os

# 初始化 Flask 应用
app = Flask(__name__)
app.secret_key = 'your-secret-key-here'  # 用于 session 加密

# ==================== 数据初始化 ====================
# 所有电视剧
shows = {
    "s001": TVShow("s001", "Breaking Bad", "Crime", 9.5, "化学老师变毒枭"),
    "s002": TVShow("s002", "Stranger Things", "Sci-Fi", 8.7, "80年代超自然谜团"),
    "s003": TVShow("s003", "The Office", "Comedy", 9.0, "办公室搞笑日常"),
    "s004": TVShow("s004", "Game of Thrones", "Fantasy", 9.2, "权力的游戏"),
    "s005": TVShow("s005", "Dark", "Sci-Fi", 8.8, "时间旅行之谜"),
}

# 所有用户
users = {
    "u001": User("u001", "Alice"),
    "u002": User("u002", "Bob"),
}

# 当前登录用户 ID(模拟)
CURRENT_USER_ID = "u001"  # 可扩展为多用户登录


# ==================== 路由定义 ====================

@app.route('/')
def index():
    current_user = users.get(CURRENT_USER_ID)
    all_shows = list(shows.values())
    return render_template('index.html', 
                         shows=all_shows, 
                         user=current_user,
                         shows=shows.values(),
                         user=current_user)


@app.route('/like/<show_id>')
def like_show(show_id):
    user = users.get(CURRENT_USER_ID)
    if user and show_id in shows:
        user.like(show_id)
    return redirect(url_for('index'))


@app.route('/recommend')
def recommend():
    user = users.get(CURRENT_USER_ID)
    recs = get_recommendations(user, shows, users)
    return render_template('recommend.html', 
                         recommendations=recs, 
                         user=user)


@app.route('/users')
def list_users():
    return render_template('users.html', users=users.values())

# ==================== 启动入口 ====================
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

debug=True 开启调试模式,代码修改自动重启。


🎨 七、前端页面设计(HTML + Bootstrap)

1. 布局母版 —— templates/base.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>电视剧趣推系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .card { margin-bottom: 1rem; }
        .btn-like { background-color: #e74c3c; color: white; }
        .btn-like:hover { background-color: #c0392b; }
    </style>
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="/">📺 趣推系统</a>
            <div class="navbar-nav">
                <a class="nav-link" href="/">首页</a>
                <a class="nav-link" href="/recommend">推荐</a>
                <a class="nav-link" href="/users">用户</a>
            </div>
        </div>
    </nav>

    <div class="container mt-4">
        {% block content %}{% endblock %}
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

2. 首页 —— templates/index.html

{% extends "base.html" %}

{% block content %}
<h2>🎬 所有电视剧</h2>
<p class="text-muted">当前用户:{{ user.name }}</p>

<div class="row">
{% for show in shows %}
    <div class="col-md-6 col-lg-4 mb-4">
        <div class="card h-100">
            <div class="card-body">
                <h5 class="card-title">{{ show.title }}</h5>
                <p class="card-text text-muted">
                    {{ show.genre }} | ⭐ {{ show.rating }}
                </p>
                <p class="card-text">{{ show.description }}</p>
                
                {% if user.has_liked(show.id) %}
                    <span class="badge bg-success">已喜欢</span>
                {% else %}
                    <a href="/like/{{ show.id }}" class="btn btn-sm btn-like">❤️ 喜欢</a>
                {% endif %}
            </div>
        </div>
    </div>
{% endfor %}
</div>
{% endblock %}

3. 推荐页 —— templates/recommend.html

{% extends "base.html" %}

{% block content %}
<h2>✨ 为你推荐</h2>
<p class="text-muted">基于你的喜好:科幻、高分优先</p>

{% if recommendations %}
<div class="row">
{% for show in recommendations %}
    <div class="col-md-6 col-lg-4 mb-4">
        <div class="card">
            <div class="card-body">
                <h5 class="card-title">{{ show.title }}</h5>
                <p class="card-text text-muted">{{ show.genre }} | ⭐ {{ show.rating }}</p>
                <p class="card-text">{{ show.description }}</p>
            </div>
        </div>
    </div>
{% endfor %}
</div>
{% else %}
<div class="alert alert-info">暂无推荐内容,请先喜欢一些剧集!</div>
{% endif %}

<a href="/" class="btn btn-primary">返回首页</a>
{% endblock %}

4. 用户页 —— templates/users.html

{% extends "base.html" %}

{% block content %}
<h2>👥 用户列表</h2>

<table class="table table-striped">
    <thead>
        <tr>
            <th>用户名</th>
            <th>喜欢数量</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
    {% for u in users %}
        <tr>
            <td>{{ u.name }}</td>
            <td>{{ u.liked_count }}</td>
            <td>
                <a href="/recommend" class="btn btn-sm btn-outline-primary">查看推荐</a>
            </td>
        </tr>
    {% endfor %}
    </tbody>
</table>

<a href="/" class="btn btn-secondary">返回首页</a>
{% endblock %}

▶️ 八、运行教程(手把手教学)

步骤 1:创建文件夹和文件

tv_recommender/
├── app.py
├── templates/
│   ├── base.html
│   ├── index.html
│   ├── recommend.html
│   └── users.html

步骤 2:安装 Flask(如未安装)

pip install flask

步骤 3:运行程序

cd tv_recommender
python app.py

✅ 输出:

* Running on http://127.0.0.1:5000

步骤 4:打开浏览器访问

👉 访问:http://127.0.0.1:5000


🖼️ 九、运行效果模拟(文字版)

首页 /

  • 显示 5 部电视剧卡片
  • Alice 用户看到《Stranger Things》旁有 ❤️ 按钮
  • 点击后变为“已喜欢”

推荐页 /recommend

  • 显示《Dark》等科幻高分剧
  • 因为 Alice 喜欢过《Stranger Things》(Sci-Fi)

用户页 /users

  • 列出 Alice 和 Bob
  • 显示每人喜欢数量

🔍 十、常见问题与解决方案

问题解决方案
TemplateNotFound检查 templates/ 文件夹名是否拼写正确
jinja2.exceptions.UndefinedError检查变量名是否传入 render_template()
Method Not Allowed确保 POST 请求有 @app.route(..., methods=['POST'])
PickleError with session不要存复杂对象到 session,只存 ID

🔮 十一、扩展方向(进阶练习)

方向实现思路
🗄️ SQLite 数据库sqlite3 存储 showsusers
🔐 用户登录添加登录表单,用 session['user_id'] 记录
📊 多标签推荐genre 改为 list,支持“科幻+悬疑”
📱 REST API提供 /api/recommend?user=u001 接口
🎨 前端美化引入 Vue/React,做 SPA 单页应用

📦 十二、项目打包与部署建议

# 打包为 zip
zip -r tv_recommender.zip tv_recommender/

# 部署到云服务器(Ubuntu)
sudo apt install python3-pip
pip3 install flask
nohup python3 app.py &

或使用 gunicorn + nginx 生产部署。


📝 十三、总结

通过本次重构,你学会了:

  • ✅ 如何将控制台程序升级为 Web 应用
  • ✅ Flask 路由、模板、静态文件管理
  • ✅ Jinja2 模板语法(循环、条件、继承)
  • ✅ 推荐系统 Web 化实现
  • ✅ Python Web 开发全流程

💬 一句话总结:Java 是基础,Python + Flask 是快速落地 Web 项目的利器。掌握它,你就能把想法变成可交互的产品!


❤️ 结束语

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!也欢迎在评论区留下你的运行截图或提问。

📌 关注我,后续将带来:《Flask + SQLite 版》《Vue + Flask 前后端分离》《推荐算法升级:协同过滤》等系列教程!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值