282-基于Python的豆瓣音乐可视化分析推荐系统

豆瓣音乐可视化分析推荐系统 - 技术文档

目录

  • [1. 项目概述](#1. 项目概述)
  • [2. 技术架构](#2. 技术架构)
  • [3. 后端技术](#3. 后端技术)
  • [4. 前端技术](#4. 前端技术)
  • [5. 数据库设计](#5. 数据库设计)
  • [6. API接口文档](#6. API接口文档)
  • [7. 爬虫模块](#7. 爬虫模块)
  • [8. 推荐算法](#8. 推荐算法)
  • [9. 部署说明](#9. 部署说明)

1. 项目概述

1.1 项目简介

本项目是一个基于Python Flask + Vue3的豆瓣音乐可视化分析推荐系统,实现了音乐数据的爬取、存储、可视化分析和个性化推荐功能。

1.2 主要功能

  • 数据爬取:支持豆瓣音乐Top250、分类音乐、评论数据的爬取
  • 可视化分析:排名分析、表演者分析、流派分析、年度分析、热力图、评论词云
  • 个性化推荐:基于协同过滤和内容特征的混合推荐算法
  • 情感分析:基于PaddleHub的评论情感分析
  • 系统管理:用户管理、角色管理、日志管理、数据备份、系统监控

1.3 技术栈

层级 技术
后端框架 Flask 2.x
数据库 MySQL 8.0
前端框架 Vue 3 + TypeScript
UI组件库 Element Plus
图表库 ECharts 5
爬虫 Requests + Parsel + DrissionPage
情感分析 PaddleHub (senta_bilstm)
认证 JWT

2. 技术架构

2.1 系统架构图

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                         前端 (Vue3 + Element Plus)               │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │ 首页     │ │ 音乐列表 │ │ 可视化   │ │ 推荐系统 │            │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘            │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │ 爬虫管理 │ │ 系统管理 │ │ 用户管理 │ │ 大屏展示 │            │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘            │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         后端 (Flask)                             │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │ app_music│ │app_visual│ │app_system│ │app_login │            │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘            │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐                         │
│  │app_user  │ │ app_log  │ │app_file  │                         │
│  └──────────┘ └──────────┘ └──────────┘                         │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         数据层                                   │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐                         │
│  │  MySQL   │ │ 文件存储 │ │ 豆瓣API  │                         │
│  └──────────┘ └──────────┘ └──────────┘                         │
└─────────────────────────────────────────────────────────────────┘

2.2 项目目录结构

复制代码
code/
├── m_server/                    # 后端代码
│   ├── app.py                   # Flask主程序入口
│   ├── app_music.py             # 音乐相关API
│   ├── app_visual.py            # 可视化API
│   ├── app_system.py            # 系统管理API
│   ├── app_login.py             # 登录认证API
│   ├── app_user.py              # 用户管理API
│   ├── app_log.py               # 日志API
│   ├── app_file.py              # 文件上传API
│   ├── model_recommend.py       # 推荐算法模块
│   ├── spider_music_top250.py   # Top250爬虫
│   ├── spider_music_all.py      # 分类音乐爬虫
│   ├── spider_comment.py        # 评论爬虫
│   ├── spider_log.py            # 爬虫日志工具
│   ├── spider_download_image.py # 图片下载模块
│   ├── utils/                   # 工具类
│   │   ├── u_mysql.py           # 数据库连接
│   │   ├── auth.py              # JWT认证
│   │   ├── u_time.py            # 时间工具
│   │   └── GenerateUUID.py      # UUID生成
│   └── backups/                 # 数据库备份目录
│
├── m_web/                       # 前端代码
│   ├── src/
│   │   ├── views/               # 页面组件
│   │   │   ├── business/        # 业务页面
│   │   │   │   ├── index/       # 首页
│   │   │   │   ├── analysis/    # 分析页面
│   │   │   │   ├── recommend.vue# 推荐页面
│   │   │   │   └── musicEdit.vue# 音乐编辑
│   │   │   ├── spider/          # 爬虫管理
│   │   │   ├── system/          # 系统管理
│   │   │   └── largeScreen/     # 大屏展示
│   │   ├── components/          # 公共组件
│   │   ├── api/                 # API接口
│   │   ├── router/              # 路由配置
│   │   ├── store/               # 状态管理(Pinia)
│   │   └── utils/               # 工具函数
│   └── dist/                    # 构建产物
│
└── design_282_music.sql         # 数据库初始化脚本

3. 后端技术

3.1 Flask应用结构

主程序入口 app.py

python 复制代码
from flask import Flask
app = Flask(__name__)
app.config["SECRET_KEY"] = os.urandom(24).hex()

# 注册蓝图
app.register_blueprint(music_api, url_prefix='/music')
app.register_blueprint(visual_api, url_prefix='/visual')
app.register_blueprint(system_api, url_prefix='/system')
app.register_blueprint(login_api, url_prefix='/login')
app.register_blueprint(user_api, url_prefix='/user')
app.register_blueprint(log_api, url_prefix='/log')
app.register_blueprint(file_api, url_prefix='/file')

# 启动服务
app.run(host="127.0.0.1", port=8066, debug=True)

3.2 数据库连接

使用PyMySQL封装的连接池 utils/u_mysql.py

python 复制代码
MYSQL_config = {
    'host': "localhost",
    'port': 3306,
    'user': 'root',
    'password': '123456',
    'database': 'design_282_music',
}

class MySQLConnect:
    def __init__(self, cursorclass=DictCursor, config=MYSQL_config):
        self.connection = pymysql.connect(**config, charset='utf8mb4')
        self.connection.autocommit(True)

    def fetchone(self, sql, params=None): ...
    def fetchall(self, sql, params=None): ...
    def execute(self, sql, params=None): ...

def get_a_conn(cursorclass=DictCursor):
    return MySQLConnect(cursorclass)

3.3 JWT认证

utils/auth.py 实现JWT令牌认证:

python 复制代码
SECRET_KEY = 'douban_music_282_secret_key_2024'
TOKEN_EXPIRE_SECONDS = 86400  # 24小时

def generate_token(user_id, role, account, name):
    payload = {
        'user_id': user_id,
        'role': role,
        'account': account,
        'name': name,
        'exp': int(time.time()) + TOKEN_EXPIRE_SECONDS
    }
    return jwt.encode(payload, SECRET_KEY, algorithm='HS256')

def login_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        user = get_current_user()
        if not user:
            return jsonify({'code': 401, 'msg': '未登录或Token已过期'})
        return f(*args, **kwargs)
    return decorated

def admin_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        user = get_current_user()
        if not user:
            return jsonify({'code': 401, 'msg': '未登录或Token已过期'})
        if user['role'] != '1':
            return jsonify({'code': 403, 'msg': '无权限访问'})
        return f(*args, **kwargs)
    return decorated

3.4 API模块划分

模块 文件 URL前缀 功能
音乐模块 app_music.py /api/music 音乐CRUD、收藏、推荐
可视化模块 app_visual.py /api/visual 各类分析图表数据
系统模块 app_system.py /api/system 配置、定时任务、爬虫
登录模块 app_login.py /api/login 登录、注册、修改密码
用户模块 app_user.py /api/user 用户管理
日志模块 app_log.py /api/log 操作日志
文件模块 app_file.py /api/file 文件上传

4. 前端技术

4.1 技术栈

  • 框架: Vue 3 + TypeScript
  • 构建工具: Vite
  • UI组件: Element Plus
  • 图表: ECharts 5
  • 状态管理: Pinia
  • 路由: Vue Router 4
  • HTTP: Axios

4.2 路由配置

typescript 复制代码
// 主要路由
const routes = [
  { path: '/dashboard', component: () => import('@/views/business/index/index.vue') },
  { path: '/analysis/ranking', component: 'business/analysis/ranking' },
  { path: '/analysis/author', component: 'business/analysis/author' },
  { path: '/analysis/schools', component: 'business/analysis/schools' },
  { path: '/analysis/year', component: 'business/analysis/year' },
  { path: '/recommend', component: () => import('@/views/business/recommend.vue') },
  { path: '/spider', component: () => import('@/views/spider/index.vue') },
  { path: '/user', component: () => import('@/views/system/user/index.vue') },
  { path: '/systemManage/logManage', component: 'system/logManage' },
  { path: '/largeScreen', component: () => import('@/views/largeScreen/index.vue') },
]

4.3 主要页面

页面 路径 功能
首页 /dashboard 数据概览、快捷入口
音乐列表 /dashboard 音乐浏览、搜索、收藏
排名分析 /analysis/ranking 流派占比、评分排名
表演者分析 /analysis/author 作品数量、均分排名
流派分析 /analysis/schools 流派分布、情感统计
年度分析 /analysis/year 年度发布趋势
热力图 /analysis/heatmap 年份-流派热力图
评论分析 /analysis/comments 评论词云、情感分析
音乐推荐 /recommend 个性化推荐结果
数据爬取 /spider 爬虫操作界面
爬取历史 /dataLog 爬虫日志列表
用户管理 /user 用户CRUD
角色管理 /roleManage 角色权限
日志管理 /systemManage/logManage 系统日志查询
系统配置 /systemManage/systemConfig 参数配置
大屏展示 /largeScreen 数据可视化大屏

5. 数据库设计

5.1 核心表结构

tbl_music (音乐表)
字段 类型 说明
id VARCHAR(32) 主键,豆瓣音乐ID
name VARCHAR(255) 音乐名称
author VARCHAR(255) 表演者
schools VARCHAR(100) 流派
rating_star DECIMAL(3,1) 评分
rating_user INT 评价人数
release_date VARCHAR(20) 发行时间
type VARCHAR(50) 专辑类型
medium VARCHAR(50) 介质
press VARCHAR(255) 出版者
photo VARCHAR(500) 封面图片URL
introduce TEXT 简介
song TEXT 曲目
top CHAR(1) 是否Top250 (1/0)
create_time DATETIME 创建时间
tbl_comment (评论表)
字段 类型 说明
id INT AUTO_INCREMENT 主键
name_cn VARCHAR(255) 音乐名称
href VARCHAR(32) 关联音乐ID
people_name VARCHAR(100) 评论者
people_href VARCHAR(200) 评论者主页
comments_time VARCHAR(50) 评论时间
content TEXT 评论内容
sentiment_label VARCHAR(20) 情感标签
sentiment_key VARCHAR(20) 情感键(positive/negative)
positive_probs DECIMAL(5,2) 正面概率
negative_probs DECIMAL(5,2) 负面概率
tbl_collect (收藏表)
字段 类型 说明
id INT AUTO_INCREMENT 主键
user_id VARCHAR(32) 用户ID
music_id VARCHAR(32) 音乐ID
category_name VARCHAR(50) 收藏分类
create_time DATETIME 收藏时间
tbl_recommend_history (推荐历史表)
字段 类型 说明
id VARCHAR(32) 主键
batch_id VARCHAR(50) 批次ID
user_id VARCHAR(32) 用户ID
music_id VARCHAR(32) 音乐ID
title VARCHAR(255) 音乐名称
score VARCHAR(10) 推荐得分
feedback VARCHAR(20) 用户反馈(click/collect/ignore)
recommend_time DATETIME 推荐时间
tbl_log (爬虫日志表)
字段 类型 说明
id VARCHAR(32) 主键
user_name VARCHAR(50) 操作用户
spider_type VARCHAR(50) 爬取类型
start_time DATETIME 开始时间
end_time DATETIME 结束时间
status CHAR(1) 状态(1执行中/2成功/3失败)
data_url VARCHAR(500) 数据地址
start_page INT 开始页
end_page INT 结束页
log TEXT 日志内容
sys_user (用户表)
字段 类型 说明
id VARCHAR(32) 主键
account VARCHAR(50) 账号
password VARCHAR(100) 密码(MD5)
name VARCHAR(50) 昵称
role VARCHAR(10) 角色(1管理员/2普通用户)
status CHAR(1) 状态(0禁用/1启用)
sys_operation_log (操作日志表)
字段 类型 说明
id VARCHAR(32) 主键
user_id VARCHAR(32) 用户ID
user_name VARCHAR(50) 用户名
operation VARCHAR(50) 操作类型
method VARCHAR(200) 接口路径
params TEXT 参数
ip VARCHAR(50) IP地址
create_time DATETIME 创建时间
sys_config (系统配置表)
字段 类型 说明
id INT AUTO_INCREMENT 主键
config_key VARCHAR(100) 配置键
config_value TEXT 配置值
update_time DATETIME 更新时间
sys_schedule (定时任务表)
字段 类型 说明
id VARCHAR(32) 主键
name VARCHAR(100) 任务名称
spider_type VARCHAR(50) 爬取类型
cron_expr VARCHAR(50) Cron表达式
data_count INT 数据数量
status CHAR(1) 状态
last_run_time DATETIME 最后运行时间

5.2 ER关系图

复制代码
┌─────────────┐       ┌─────────────┐       ┌─────────────┐
│  sys_user   │       │  tbl_music  │       │ tbl_comment │
├─────────────┤       ├─────────────┤       ├─────────────┤
│ id          │───┐   │ id          │───┐   │ href        │
│ account     │   │   │ name        │   │   │ content     │
│ name        │   │   │ author      │   │   │ sentiment   │
│ role        │   │   │ rating_star │   │   └─────────────┘
└─────────────┘   │   └─────────────┘   │
      │           │         │           │
      │           │         │           │
      ▼           │         ▼           │
┌─────────────┐   │   ┌─────────────┐   │
│ tbl_collect │   │   │tbl_recommend│   │
├─────────────┤   │   │ _history    │   │
│ user_id     │───┘   ├─────────────┤   │
│ music_id    │───────│ music_id    │───┘
│ category    │       │ user_id     │
└─────────────┘       │ feedback    │
                      └─────────────┘

6. API接口文档

6.1 认证接口

登录
复制代码
POST /api/login/login
Request: { "account": "admin", "password": "123456" }
Response: {
  "code": 0,
  "msg": "登录成功",
  "data": { "token": "eyJ...", "user": {...} }
}
获取用户信息
复制代码
GET /api/login/userInfo
Headers: Authorization: Bearer <token>
Response: { "code": 0, "data": { "id", "account", "name", "role" } }

6.2 音乐接口

音乐列表
复制代码
GET /api/music/page?pageNo=1&pageSize=10&title=&author=&schools=
Response: {
  "code": 0,
  "data": {
    "records": [...],
    "total": 100
  }
}
音乐详情
复制代码
GET /api/music/detail?id=123456
Response: { "code": 0, "data": { 音乐详情对象 } }
收藏音乐
复制代码
POST /api/music/collect
Request: { "music_id": "123456", "category_name": "默认" }
Response: { "code": 0, "msg": "收藏成功" }
取消收藏
复制代码
POST /api/music/delCollect
Request: { "music_id": "123456" }
Response: { "code": 0, "msg": "取消收藏成功" }
我的收藏列表
复制代码
GET /api/music/myCollect?pageNo=1&pageSize=10&category_name=
Response: { "code": 0, "data": [...], "total": 50 }
收藏分类列表
复制代码
GET /api/music/collectCategories
Response: { "code": 0, "data": ["默认", "喜欢的", "待听"] }
个性化推荐
复制代码
GET /api/music/myRecommend
Response: {
  "code": 0,
  "data": [ 推荐音乐列表 ],
  "batch_id": "20260526225448_1"
}
推荐反馈
复制代码
POST /api/music/recommendFeedback
Request: { "music_id": "123", "batch_id": "xxx", "feedback": "click" }
Response: { "code": 0, "msg": "反馈成功" }

6.3 可视化接口

排名分析
复制代码
GET /api/visual/rankAnalysis?dataType=
Response: {
  "code": 0,
  "data": {
    "lpzb": [{ "name": "流行", "value": 100 }],  // 流派占比
    "pfpm": [...],  // 评分排名
    "pjrspm": [...]  // 评价人数排名
  }
}
表演者分析
复制代码
GET /api/visual/authorAnalysis?dataType=
Response: {
  "code": 0,
  "data": {
    "zpsl": [...],  // 作品数量
    "jfpm": [...],  // 均分排名
    "qgfx": [...]   // 情感分布
  }
}
流派分析
复制代码
GET /api/visual/schoolsAnalysis?dataType=
年度分析
复制代码
GET /api/visual/yearAnalysis?dataType=
热力图数据
复制代码
GET /api/visual/heatmapData?dataType=&metric=count
Response: {
  "code": 0,
  "data": {
    "heatmap": [[year_index, school_index, value], ...],
    "year_labels": ["2020", "2021", ...],
    "school_labels": ["流行", "摇滚", ...]
  }
}
评论词云
复制代码
GET /api/visual/commentCloud?author=
Response: {
  "code": 0,
  "data": {
    "opinionStats": [...],  // 情感占比
    "cloudData": [...]      // 词云数据
  }
}

6.4 系统管理接口

爬虫执行
复制代码
POST /api/system/scheduleRun
Request: {
  "spiderType": "0",  // 0=分类音乐, Top250=Top250
  "type": "流行",     // 风格类型
  "startPage": 1,
  "endPage": 5
}
Response: {
  "code": 0,
  "msg": "任务已触发",
  "data": { "task_id": "xxx", "log_id": "xxx" }
}
爬虫进度查询
复制代码
GET /api/system/spiderProgress?log_id=xxx
Response: {
  "code": 0,
  "data": {
    "status": "running",  // running/done/error
    "progress": 50,
    "message": "正在爬取第3页...",
    "log": ["日志行1", "日志行2"]
  }
}
日志列表
复制代码
GET /api/system/logList?page=1&size=20&log_type=spider&keyword=
Response: {
  "code": 0,
  "data": {
    "records": [...],
    "total": 100
  }
}
清理日志
复制代码
POST /api/system/cleanLogs
Request: { "id": "xxx" }  // 删除单条
或: { "days": 30, "log_type": "all" }  // 批量清理
Response: { "code": 0, "msg": "删除成功" }
系统配置列表
复制代码
GET /api/system/configList
Response: { "code": 0, "data": [...] }
保存系统配置
复制代码
POST /api/system/configSave
Request: { "configs": [{ "config_key": "xxx", "config_value": "yyy" }] }
Response: { "code": 0, "msg": "保存成功" }
数据清洗
复制代码
POST /api/system/dataClean
Response: { "code": 0, "msg": "数据清洗完成" }
数据校验报告
复制代码
GET /api/system/dataValidate
Response: {
  "code": 0,
  "data": {
    "total": 1000,
    "empty_name": 5,
    "bad_rating": 3,
    "duplicates": 2,
    "health_rate": 99.0
  }
}
系统监控
复制代码
GET /api/system/monitor
Response: {
  "code": 0,
  "data": {
    "cpu_percent": 25.5,
    "memory": { "total": 16, "used": 8, "percent": 50 },
    "disk": { "total": 500, "used": 200, "percent": 40 },
    "today_api_calls": 150,
    "api_calls_7d": [...],
    "recent_errors": [...]
  }
}

7. 爬虫模块

7.1 爬虫架构

复制代码
┌─────────────────────────────────────────────────────────┐
│                    爬虫调度器                            │
│  ┌─────────────────────────────────────────────────┐   │
│  │ app_system.py: schedule_run()                    │   │
│  │ - 接收爬取请求                                    │   │
│  │ - 创建日志记录                                    │   │
│  │ - 启动异步线程执行                                │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘
                          │
          ┌───────────────┼───────────────┐
          ▼               ▼               ▼
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ Top250爬虫  │   │ 分类音乐爬虫│   │ 评论爬虫    │
│ spider_     │   │ spider_     │   │ spider_     │
│ music_top250│   │ music_all   │   │ comment     │
└─────────────┘   └─────────────┘   └─────────────┘
          │               │               │
          └───────────────┼───────────────┘
                          ▼
┌─────────────────────────────────────────────────────────┐
│                    数据处理流程                          │
│  1. 获取列表页 → 2. 获取详情页 → 3. 数据解析            │
│  4. 数据入库 → 5. 下载封面 → 6. 更新日志                │
└─────────────────────────────────────────────────────────┘

7.2 Top250爬虫

文件 : spider_music_top250.py

功能: 爬取豆瓣音乐Top250排行榜

流程:

  1. 遍历Top250分页(共10页,每页25条)
  2. 解析列表页获取音乐ID、封面、评分
  3. 访问详情页获取完整信息
  4. 存入临时表 tmp_music
  5. 爬取完成后转移至 tbl_music
  6. 下载封面图片

关键技术:

  • 使用 requests 发送HTTP请求
  • 使用 parsel.Selector 解析HTML
  • 模拟浏览器Headers绕过反爬

7.3 分类音乐爬虫

文件 : spider_music_all.py

功能: 按风格类型爬取分类音乐

流程:

  1. 接收风格类型(流行、摇滚、电子等)
  2. 按页码范围爬取列表页
  3. 使用 DrissionPage 绕过动态加载
  4. 解析详情并存入 tbl_music

关键技术:

  • DrissionPage: 处理JavaScript动态渲染
  • 监听数据包获取API响应

7.4 评论爬虫

文件 : spider_comment.py

功能: 爬取音乐评论并进行情感分析

流程:

  1. 查询无评论的音乐列表
  2. 逐个爬取评论页
  3. 解析评论内容存入 tbl_comment
  4. 使用PaddleHub进行情感分析
  5. 更新情感标签和概率

情感分析:

python 复制代码
import paddlehub as hub
senta = hub.Module(name="senta_bilstm")
results = senta.sentiment_classify(data={"text": comments_list})
# 结果包含: sentiment_label, sentiment_key, positive_probs, negative_probs

7.5 爬虫日志

文件 : spider_log.py

python 复制代码
# 新增日志
def insertLog(id, user_name, start_time, end_time, status,
              data_url, start_page, end_page, log, spider_type):
    sql = """INSERT INTO tbl_log (id, user_name, start_time, end_time,
             status, data_url, start_page, end_page, log, spider_type)
             VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""

# 更新日志(data_url为空时不覆盖)
def updateLog(id, user_name, end_time, status, data_url,
              start_page, end_page, log):
    if data_url:
        # 更新所有字段
    else:
        # 不更新data_url,保留原值

7.6 反爬策略

  1. 请求头伪装: 模拟Chrome浏览器
  2. 随机延时: 每次请求间隔0-3秒
  3. Cookie池: 使用真实登录Cookie
  4. 数据包监听: DrissionPage监听API响应

8. 推荐算法

8.1 算法概述

采用混合推荐算法,结合协同过滤和内容特征:

复制代码
最终得分 = CF得分 × 0.6 + 内容得分 × 0.4

8.2 ItemCF协同过滤

原理: 基于物品的协同过滤,计算物品相似度

python 复制代码
def _item_similarity(item_users):
    """计算物品相似度"""
    sim = defaultdict(dict)
    for item_a, item_b in combinations(items, 2):
        users_a = item_users[item_a]
        users_b = item_users[item_b]
        common = len(users_a & users_b)  # 共同收藏用户数
        if common > 0:
            w = common / sqrt(len(users_a) * len(users_b))
            sim[item_a][item_b] = w
            sim[item_b][item_a] = w
    return sim

def _recommend_by_cf(user_id, user_items, item_sim, top_n):
    """基于相似物品推荐"""
    scores = defaultdict(float)
    for item_id in user_items[user_id]:  # 用户收藏的物品
        for related_item, similarity in item_sim[item_id].items():
            if related_item not in user_items[user_id]:
                scores[related_item] += similarity
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)[:top_n]

8.3 内容特征推荐

原理: 基于用户收藏的音乐特征推荐相似音乐

python 复制代码
def _recommend_by_content(user_id, collected_ids, music_dict, feedback_boost):
    """基于内容特征推荐"""
    # 分析用户偏好
    author_count = defaultdict(int)    # 表演者偏好
    schools_count = defaultdict(int)   # 流派偏好

    for mid in collected_ids:
        m = music_dict[mid]
        author_count[m['author']] += 1
        schools_count[m['schools']] += 1

    # 计算推荐得分
    scores = {}
    for mid, m in music_dict.items():
        if mid in collected_ids:
            continue
        score = 0
        if m['author'] in author_count:
            score += author_count[m['author']] * 0.3 * feedback_boost['author']
        if m['schools'] in schools_count:
            score += schools_count[m['schools']] * 0.2 * feedback_boost['schools']
        if m['rating_star']:
            score += float(m['rating_star']) / 10 * 0.1 * feedback_boost['score']
        scores[mid] = score
    return scores

8.4 反馈权重调整

根据用户对推荐结果的反馈动态调整权重:

python 复制代码
def _get_feedback_weights(mysql, user_id):
    """根据用户反馈调整权重"""
    boost = {'author': 1.0, 'schools': 1.0, 'score': 1.0}

    # 统计历史反馈
    for row in feedback_history:
        if feedback == 'click':    delta = +0.1
        elif feedback == 'collect': delta = +0.3
        elif feedback == 'ignore':  delta = -0.2

        # 累计调整幅度
        boost['author'] = clamp(0.5, 2.0, 1.0 + avg_author_delta)
        boost['schools'] = clamp(0.5, 2.0, 1.0 + avg_schools_delta)

    return boost

8.5 冷启动处理

新用户无收藏数据时,返回热门音乐:

python 复制代码
def _get_popular_music(mysql, top_n, collected_ids):
    """热门推荐(冷启动)"""
    sql = """SELECT * FROM tbl_music
             WHERE rating_star IS NOT NULL
             ORDER BY rating_star DESC, rating_user DESC
             LIMIT %s"""
    return [m for m in result if m['id'] not in collected_ids][:top_n]

9. 部署说明

9.1 环境要求

后端:

  • Python 3.8+
  • MySQL 8.0+
  • Chrome浏览器(爬虫需要)

前端:

  • Node.js 18+
  • npm 9+

9.2 后端部署

bash 复制代码
# 1. 安装依赖
pip install flask flask-cors pymysql jwt pyjwt requests parsel
pip install drissionpage paddlehub coloredlogs psutil

# 2. 安装PaddleHub情感分析模型
python -c "import paddlehub as hub; hub.Module(name='senta_bilstm')"

# 3. 创建数据库
mysql -u root -p -e "CREATE DATABASE design_282_music CHARACTER SET utf8mb4"

# 4. 导入数据表
mysql -u root -p design_282_music < design_282_music.sql

# 5. 修改数据库配置
# 编辑 m_server/utils/u_mysql.py 中的 MYSQL_config

# 6. 启动后端服务
cd m_server
python app.py
# 服务地址: http://127.0.0.1:8066

9.3 前端部署

bash 复制代码
# 1. 安装依赖
cd m_web
npm install

# 2. 开发模式
npm run dev

# 3. 生产构建
npm run build
# 产物在 dist/ 目录

# 4. 部署到Nginx
# nginx.conf:
server {
    listen 80;
    server_name localhost;

    location / {
        root /path/to/m_web/dist;
        try_files $uri $uri/ /index.html;
    }

    location /api {
        proxy_pass http://127.0.0.1:8066;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

9.4 配置文件

数据库配置 m_server/utils/u_mysql.py:

python 复制代码
MYSQL_config = {
    'host': 'localhost',
    'port': 3306,
    'user': 'root',
    'password': 'your_password',
    'database': 'design_282_music',
}

JWT密钥 m_server/utils/auth.py:

python 复制代码
SECRET_KEY = 'your_secret_key_here'
TOKEN_EXPIRE_SECONDS = 86400  # 24小时

9.5 默认账号

  • 管理员: admin / 123456
  • 普通用户: user / 123456

附录

A. 操作日志类型

操作类型 说明
BROWSE 浏览音乐
COLLECT 收藏音乐
UNCOLLECT 取消收藏
SEARCH 搜索音乐
RECOMMEND_CLICK 推荐点击
EDIT 编辑数据
DELETE 删除数据
IMPORT 导入数据
EXPORT 导出数据

B. 爬虫状态码

状态码 说明
1 执行中
2 执行成功
3 执行失败

C. 用户角色

角色ID 说明
1 管理员
2 普通用户

D. 音乐流派列表

  • 电子、古典、流行、电影原声、中国摇滚
  • 钢琴、民谣、纯音乐、原声、摇滚
  • 独立音乐、经典等

文档版本 : 1.0

更新日期 : 2026-05-26

作者: 系统开发团队

相关推荐
星原望野1 小时前
JAVA:策略模式的实战使用
java·开发语言·策略模式
LJianK11 小时前
java多态
java·开发语言·python
_Evan_Yao1 小时前
栈与队列:后进先出与先进先出的智慧
开发语言·python
J2虾虾1 小时前
Spring AI Alibaba - Skills 技能
人工智能·python·spring
z落落1 小时前
C# 构造函数(无参/有参/重载/this)+析构函数(终结器)|GC 垃圾回收
java·开发语言·c#
汽车仪器仪表相关领域1 小时前
Kvaser Hybrid CAN/LIN 单通道三合一总线分析仪:高性价比CAN FD/LIN集成测试利器
运维·服务器·网络·数据挖掘·数据分析·单元测试·集成测试
带派擂总1 小时前
Python全栈开发 Day08_控制文件指针移动 异常捕获 推导式
python
XLYcmy2 小时前
面向Agent权限系统的快速审计工具
python·网络安全·ai·llm·飞书·agent·字节跳动
kkeeper~2 小时前
0基础C语言积跬步之自定义类型结构体
c语言·开发语言