ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于Django的鞋类商品推荐与可视化大屏系统实现

基于Django的鞋类商品推荐与可视化大屏系统实现 1. 项目概览与整体架构设计1.1 这个毕设项目到底在做什么看到这个标题你应该和我最开始接到这类需求时的感受一样——又是一个集大数据爬取、推荐算法、可视化大屏于一体的“全家桶”式毕业设计。但拆开看其实并不复杂核心就三条线数据从哪来、推荐怎么算、结果怎么展示。先把这个项目定位说清楚。这是一套基于Python Django框架开发的鞋类商品数据可视化与推荐系统数据面向电商平台的球鞋商品信息。系统做三件事第一从电商站点采集鞋类商品的基础数据包括价格、销量、上架时间、品牌、款式标签第二基于协同过滤推荐算法给用户做个性化商品推荐第三将数据分析结果以可视化大屏的形式呈现出来方便运营人员和管理者直观掌握市场动态。这个项目非常适合作为计算机科学与技术、软件工程、大数据相关专业的毕业设计选题。难度梯度合理Django框架上手快协同过滤算法是机器学习领域最经典的入门算法之一可视化层用ECharts可以直接复用大量成熟案例。即使你只有Python基础和一点Web开发经验也有能力在两个月内做完并写出像样的论文。有人可能会问为什么偏偏选鞋类商品这里有一个很实际的考虑鞋类商品尤其是潮流球鞋数据维度丰富——品牌、系列、配色、发售价格、二级市场溢价幅度、销量热度天然适合做数据分析展示。而且相比服装、数码产品的数据鞋类数据的波动规律更强更利于在可视化大屏上呈现“趋势感”和“对比感”论文里的截图效果也更漂亮。1.2 技术选型与架构分层技术选型上骨架是Django MySQL ECharts Pandas Scikit-learn这个组合是同类毕设中使用频率最高、也最稳妥的方案。我为什么推荐Django而不是Flask核心原因是Django自带的Admin后台、ORM和认证体系能省掉大量重复开发。毕设阶段你需要快速产出可演示的系统Django的ORM可以让你用Python类定义数据表迁移工具一键同步数据库结构Admin后台在中期调试阶段可以直接看到数据入库情况省去写管理页面的时间。Flask虽然更轻量但权限、数据库迁移这些都要自己搭时间成本高出一截。架构上我把它分成四层层级核心职责关键技术数据采集层爬取商品数据、用户行为数据Requests / Scrapy / Selenium数据服务层数据清洗、入库、聚合计算Pandas、MySQL、Django ORM算法推荐层协同过滤召回、排序、TopN输出Scikit-learn、NumPy可视化应用层大屏展示、后台管理、交互操作Django、ECharts、AJAX这里有个关键设计决策要提前想明白推荐算法部分到底用独立脚本计算还是集成进Django的处理链路里我建议前期算法原型用独立脚本跑通确认效果后再封装成Django的service模块。这样做的好处是调试算法时不用每次启动Web服务直接在Jupyter Notebook里验证相似度计算结果等到算法稳定后再打包复用效率高很多。另一个需要注意的架构问题是任务拆分。协同过滤计算、数据聚合、热门榜单统计这些都属于计算密集型任务如果全部放在请求处理线程里同步执行前端打开大屏页面时会卡顿好几秒。我的做法是给系统加了一层缓存机制——用Django的cache框架把推荐结果和统计结果缓存起来设置合理的过期时间比如热门榜缓存30分钟用户推荐缓存10分钟这样大屏加载速度能提升数倍答辩演示时也不会出现白屏等待的尴尬场面。2. 数据采集与预处理——系统的地基2.1 数据采集方案设计数据是整个系统的燃料没有干净的数据后面的协同过滤算法和可视化大屏都是空中楼阁。对于鞋类商品数据采集核心目标是拿到两类数据商品静态数据和用户行为数据。商品静态数据包括鞋款名称、品牌、系列、价格、销量、上架日期、图片链接、尺码区间、配色标签。用户行为数据则包括用户的浏览记录、收藏行为、加入购物车和购买记录。这里有一个现实问题真实用户行为数据属于平台核心资产任何第三方都不可能直接爬到完整的用户行为日志。所以毕设项目通常采用折中方案——商品数据从公开页面采集用户行为数据通过系统自身的Web页面埋点积累同时用脚本模拟生成一批合理的用户操作日志作为算法验证的基础数据集。实际采集技术上对于静态商品页面Requests加BeautifulSoup组合足够应对多数场景。如果目标站点是动态渲染的JavaScript页面就得换Selenium驱动浏览器获取渲染后的源码。但我给你一个建议毕设阶段不要死磕反爬机制强的站点把爬虫时间控制在总开发周期的20%以内更多精力留给算法和可视化。可以选用一些公开的电商数据接口或者直接下载公开数据集做替代——比如Kaggle上的Shoe Dataset、电商公开交易数据集一样能支撑论文和演示。在毕设答辩时解释清楚“数据来源的合理性与替代方案”比强行展示爬虫技巧更能获得老师认可。采集到的原始数据需要做字段归一化。不同来源的鞋款名称格式不统一“Air Jordan 1 Retro High OG”、“AJ1 芝加哥”、“乔丹一代复古高帮”实际指向同一个商品。这种数据如果不做归一化处理协同过滤计算出的相似商品会出现严重偏差。文本归一化的基本思路是统一小写、去掉特殊符号、做品牌词典映射、提取核心型号编码。我建议在数据库设计时增加一个item_code字段专门存放归一化后的商品唯一标识算法计算全部基于这个字段进行。2.2 数据清洗与入库采集完成只是第一步脏数据如果不处理干净算法跑出来的推荐结果会让你怀疑人生。我在实际项目里遇到过三类典型脏数据价格字段携带货币符号和单位比如“¥1,299”、“1299元”、“1.299k”直接入库会导致数值类型无法参与计算。处理方式是统一用正则提取纯数字部分再做单位换算和类型转换。销量字段缺失或为0。有些新款鞋上架时间短销量数据还没积累起来。这种数据如果直接参与协同过滤会导致商品节点孤立。我的处理方式是对销量为0的新品做热度补偿——用浏览量除以商品上架天数的比值作为热度替代指标。重复商品记录。同一双鞋因为不同尺码、不同链接被爬了多条。去重逻辑要谨慎不能简单按商品名去重而是按“品牌型号配色”组合键去重否则会把不同配色的同一鞋款误并成一条。数据入库我推荐用Pandas做清洗后批量导入MySQL而不是一条条insert。Pandas的DataFrame配合to_sql方法几万条数据几秒钟就能写入。Django ORM的bulk_create也可以但Pandas的清洗链路更直观filter去重、fillna补缺、astype转型每一步都可以在Notebook里即时验证。下面给出一个典型的清洗流程示例import pandas as pd import re # 读取原始采集数据 df pd.read_csv(shoes_raw.csv) # 清洗价格字段去掉货币符号和千分位逗号 def clean_price(val): if pd.isna(val): return None num re.sub(r[^\d.], , str(val)) return float(num) if num else None df[price_clean] df[price].apply(clean_price) # 销量缺失补偿用浏览热度替代 df[sales_comp] df[sales].fillna( df[views] / df[days_on_shelf].clip(lower1) ) # 按品牌型号配色组合键去重 df[dedup_key] df[brand].str.lower() _ \ df[model].str.lower() _ df[colorway].str.lower() df df.drop_duplicates(subsetdedup_key, keepfirst) # 价格异常值剔除低于50元或高于5万元的数据多半是错误记录 df df[(df[price_clean] 50) (df[price_clean] 50000)] # 入库 from sqlalchemy import create_engine engine create_engine(mysqlpymysql://user:passlocalhost/shoe_db) df.to_sql(products, conengine, if_existsappend, indexFalse)2.3 数据表设计与关系建模Django的ORM建模比传统SQL语句更直观但表关系设计仍然要提前想清楚。这个系统的核心表我建议建六张用户表(user)保存账号信息和基本画像字段商品表(product)保存清洗后的商品静态属性浏览行为表(browse_log)记录用户每一次商品浏览收藏表(favorite_log)记录收藏动作订单表(order)记录购买行为推荐结果表(recommendation)存储算法产出的推荐列表方便前端直接查询。这里有一个容易被忽略的设计点行为数据表务必加上action_type字段区分浏览、收藏、购买三类行为。协同过滤算法中不同类型的用户行为权重不应该相同——购买行为的置信度显然高于浏览行为。在计算用户-商品评分矩阵时可以设定浏览记1分收藏记3分购买记5分。这个加权策略能显著提升推荐质量。Django模型定义的简化示例from django.db import models class Product(models.Model): name models.CharField(max_length200, verbose_name商品名称) brand models.CharField(max_length50, verbose_name品牌) model_code models.CharField(max_length50, verbose_name型号编码, db_indexTrue) colorway models.CharField(max_length100, verbose_name配色) price models.DecimalField(max_digits10, decimal_places2, verbose_name价格) sales models.IntegerField(default0, verbose_name销量) publish_date models.DateField(nullTrue, verbose_name上架日期) image_url models.URLField(blankTrue, verbose_name图片链接) tags models.CharField(max_length200, blankTrue, verbose_name标签) class Meta: db_table product class UserBehavior(models.Model): ACTION_CHOICES [ (view, 浏览), (fav, 收藏), (buy, 购买), ] user models.ForeignKey(User, on_deletemodels.CASCADE) product models.ForeignKey(Product, on_deletemodels.CASCADE) action_type models.CharField(max_length10, choicesACTION_CHOICES) score models.FloatField(default1.0, verbose_name行为权重分) created_at models.DateTimeField(auto_now_addTrue) class Meta: db_table user_behavior建好模型后用python manage.py makemigrations和migrate同步到数据库。如果数据量在万级以下还可以在Django Admin后台直接录入少量测试数据便于联调阶段使用。3. 协同过滤推荐算法落地3.1 算法原理解读与选型决策协同过滤是推荐系统最经典的算法家族核心思想就一句话人以群分物以类聚。它分成两类——基于用户的协同过滤(UserCF)和基于物品的协同过滤(ItemCF)。UserCF的逻辑是找到和你兴趣相似的其他用户把你没看过但他们喜欢的商品推荐给你。打个比方你的室友和你都喜欢篮球鞋和跑步鞋你看中了一双AJ但没有买室友先下单了系统基于这个行为把同款推给你。ItemCF的逻辑则是找到和你历史上喜欢的商品相似的商品。比如你收藏过一双Dunk Low黑白配色系统发现这双鞋和另一双Dunk Low熊猫配色的用户行为高度重合于是把后者推给你。在鞋类电商场景下我强烈建议用ItemCF原因有两点。第一鞋类商品数量远小于用户数量。ItemCF需要计算的是商品之间的相似度矩阵商品量级在几千到几万时计算压力不大而UserCF要计算用户之间的相似度用户量级动辄上万甚至十万相似度矩阵会爆炸增长。毕设服务器的算力有限ItemCF性价比更高。第二鞋类商品的用户兴趣漂移问题。潮流人士今天关注篮球鞋明天可能转向跑鞋基于用户的协同过滤会滞后于这种兴趣变化。ItemCF天然基于“物”的关联来推荐对兴趣漂移的适应性更强。不过需要补充的是ItemCF有一个经典缺陷——它倾向于推荐热门商品导致推荐结果缺乏惊喜度也就是俗称的“长尾效应不足”。用户看过AJ1系统大概率会推AJ3、AJ4、AJ11这些同为热门系列的鞋但用户可能真正想要的是某双小众联名款。解决方法是引入多样性惩罚在生成候选集后对过于集中的品牌和系列做降权处理确保推荐列表覆盖多个品牌和品类。没有这一步你的推荐列表会显得很“单调”答辩演示时也容易被老师质疑效果。3.2 Python实现细节与代码走读推荐算法模块我用纯Python和NumPy实现没有额外引入Scikit-learn的matrix factorization工具原因是毕设论文中需要把算法原理讲清楚手写实现更便于说明每一步的逻辑也更能体现代码工作量。完整的ItemCF实现分为四步第一步构建用户-商品评分矩阵。从行为日志表中读数据按用户和商品建立二维矩阵矩阵元素是加权后的行为分数。第二步计算商品间的余弦相似度。余弦相似度的公式是cos(A,B) A·B / (|A|×|B|)在推荐系统中这个公式衡量的是两个商品向量在用户行为空间的夹角。夹角越小说明共同被消费的用户越多商品越相似。第三步根据用户的偏好商品加权汇总生成候选推荐列表。第四步过滤掉用户已经购买或浏览过的商品加入多样性控制输出TopN。import numpy as np from collections import defaultdict class ItemCF: def __init__(self): self.user_items defaultdict(dict) # 用户 - {商品: 评分} self.item_sim {} # 商品对 - 相似度 self.item_users defaultdict(set) # 商品 - 打分用户集合 def fit(self, behaviors): behaviors: [(user_id, item_id, score), ...] for user_id, item_id, score in behaviors: self.user_items[user_id][item_id] score self.item_users[item_id].add(user_id) # 计算商品间相似度 for item_a, users_a in self.item_users.items(): self.item_sim[item_a] {} for item_b, users_b in self.item_users.items(): if item_a item_b: continue # 取共同打分的用户集合 common_users users_a users_b if len(common_users) 2: continue dot sum(self._rating(u, item_a) * self._rating(u, item_b) for u in common_users) norm_a np.sqrt(sum(self._rating(u, item_a)**2 for u in users_a)) norm_b np.sqrt(sum(self._rating(u, item_b)**2 for u in users_b)) if norm_a 0 or norm_b 0: continue self.item_sim[item_a][item_b] dot / (norm_a * norm_b) def _rating(self, user_id, item_id): return self.user_items.get(user_id, {}).get(item_id, 0.0) def recommend(self, user_id, top_n10): interacted set(self.user_items[user_id].keys()) scores defaultdict(float) # 对用户交互过的每个商品累加相似商品的得分 for item, rating in self.user_items[user_id].items(): for sim_item, sim_score in self.item_sim.get(item, {}).items(): if sim_item in interacted: continue scores[sim_item] sim_score * rating # 多样性惩罚同品牌商品数量越多单项权重折损 brand_count defaultdict(int) for item in scores: brand_count[self._brand_of(item)] 1 penalized {} for item, score in scores.items(): # 简单线性惩罚第二个同品牌商品降为原权重的80% penalty 1.0 if brand_count[self._brand_of(item)] 1 else 0.8 penalized[item] score * penalty ranked sorted(penalized.items(), keylambda x: x[1], reverseTrue) return [item for item, _ in ranked[:top_n]]这段代码在几千商品、几百用户的数据规模下运行一次冷启动计算需要几十秒到几分钟。所以线上服务不能每次请求都全量重算。我的方案是后台用定时任务每天凌晨更新一次商品相似度矩阵和离线推荐结果用户访问时直接从缓存表读取推荐列表。冷启动用户无行为记录默认推荐热门商品榜这与电商行业的通用策略一致。3.3 推荐效果评估与调优推荐系统做出来之后怎么量化“推荐得好不好”是论文里必须回答的问题。我用了两组指标离线评估用准确率和召回率在线模拟用覆盖率。离线评估的做法是把行为数据按时间分成训练集和测试集比如前80%时间的行为做训练后20%做测试。对测试集中的每个用户看推荐列表中有多少商品是该用户真实消费过的。准确率是被命中商品数除以推荐列表长度召回率是被命中商品数除以用户实际消费商品数。这两个指标之间存在此消彼长的关系一般用F1分数均衡两者。实战中我的ItemCF基线模型能达到的指标大致在准确率8%-12%召回率10%-15%。这个数字看起来不高但推荐系统领域正常水平就是如此——用户的真实兴趣分布极其稀疏存在大量“推荐了但用户根本没注意到”的商品准确率能到10%已经是可以用的状态了。答辩时如果能说清楚评估逻辑和指标含义比盲目追求高分更有说服力。调优的方向有三个相似度算法切换余弦相似度换皮尔逊相关系数行为权重调整提高收藏权重、降低浏览量权重相似商品候选集截断只保留每个商品最相似的K个近邻参与计算K一般取20到50。我自己实验下来K值截断对准确率的提升最明显同时还能把计算时长缩短60%以上属于性价比最高的优化手段。4. 数据可视化大屏开发4.1 大屏布局与视觉设计思路可视化大屏是整个项目中最直观、最抓眼球的部分答辩演示时的观感基本靠它撑起来。大屏的设计遵循一条原则信息分层主次分明。屏幕中心展示核心指标次要信息绕核心周围排列。对于鞋类数据分析场景我设计的布局是顶层放标题栏和整体统计指标总商品数、总销量、平均溢价率左侧面板放品牌销量排行榜和价格区间分布右侧面板放用户活跃趋势和热门款式TOP10底部中间放一个地图或热力图展示地域销量分布。配色方案上电商数据分析大屏普遍采用深色底霓虹亮色深蓝色背景配合青色、橙色高亮这种风格对比度强视觉冲击力大适合演示环境。具体推荐色值为背景#0f1b2d主色#00d4ff辅助色#ff9f43。深色底色的另一个好处是弱化留白区域的突兀感让图表之间的过渡更平滑。大屏尺寸按1920×1080设计适配标准显示器。如果是更大的拼接屏ECharts的图表容器宽度按百分比设置可以实现自适应。不建议在这个阶段投太多精力做响应式移动端适配答辩场景绝大多数是用电脑外接投影展示优先保证桌面体验即可。前端实现层面推荐用纯HTMLCSSJavaScript引入ECharts的CDN文件不用重型的Vue或React框架。原因很直接大屏页面本质是信息展示不是复杂交互应用原生JS已完全够用。减少框架依赖答辩时被问到前端技术栈时也更容易讲清原理。4.2 ECharts核心图表实现大屏上的图表我挑了五个核心类型每个对应一种分析视角。折线图展示30天内每日销量趋势。用时间序列数据观察新品发售对整体销量的拉动效应。折线图的关键调优点是平滑曲线(smooth: true)和区域渐变填充(color渐变到底部透明)能让趋势更有质感。柱状图展示品牌销量对比。Nike、Adidas、New Balance、Jordan等品牌的销量聚合后横向排列。柱状图的正负值对比还可以做溢价率维度低于原价的和高于原价的分别用不同颜色展示。饼图或环形图展示价格区间分布。把商品价格划分为五档500元以下、500-1000、1000-2000、2000-5000、5000元以上统计每个区间的商品数量占比。这里推荐用南丁格尔玫瑰图roseType: radius在美感和信息传达上优于传统饼图。热力图展示“品牌×月份”的销量矩阵。横轴是12个月纵轴是六大品牌颜色深浅代表销量高低。热力图可以在一个图表里同时呈现两个维度的数据省空间且直观是答辩时很讨喜的图表类型。词云图展示鞋款关键词热度。从商品名称和标签中提取高频词汇字号越大代表热度越高。词云图在技术上可以用ECharts的wordCloud扩展实现注意中文词频统计前要先做分词处理推荐用jieba库。// 销量趋势折线图示例 const trendChart echarts.init(document.getElementById(trendChart)); trendChart.setOption({ backgroundColor: transparent, tooltip: { trigger: axis }, grid: { left: 6%, right: 4%, top: 15%, bottom: 6% }, xAxis: { type: category, data: days, // 日期数组由后端API提供 axisLine: { lineStyle: { color: #94a3b8 } } }, yAxis: { type: value, splitLine: { lineStyle: { color: rgba(148, 163, 184, 0.2) } } }, series: [{ name: 日销量, type: line, smooth: true, symbol: circle, symbolSize: 6, data: salesData, itemStyle: { color: #00d4ff }, areaStyle: { color: { type: linear, x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: rgba(0, 212, 255, 0.35) }, { offset: 1, color: rgba(0, 212, 255, 0) } ] } } }] });大屏页面的数据获取全部通过AJAX调用Django的API接口完成。每个图表独立请求自己的数据端点好处是单个接口出错时不会拖垮整个大屏坏处是并发请求数较多。解决方案是在前端做一次统一的Promise.all并发加载配合loading动画页面打开后约一秒内所有图表就能渲染完成。4.3 Django后端API数据对接后端API的设计要遵循一个原则后端只提供结构化数据不做任何前端渲染。每个接口返回JSON格式数据ECharts负责消费。我规划了五个API端点与前端图表一一对应/api/dashboard/overview返回顶部统计卡片数据/api/dashboard/trend返回销量趋势折线图数据/api/dashboard/brand返回品牌销量排行柱状图数据/api/dashboard/price返回价格区间分布饼图数据/api/dashboard/hot返回热门商品TOP10列表。接口实现用Django的View类写JSONResponse或者用Django REST Framework(drf)的APIView。毕设项目接口数量少直接用JsonResponse就够不用引入drf增加复杂度。关键实现细节是数据聚合。原始数据存在MySQL中但图表需要的是聚合后的统计量。比如品牌销量排行需要在后端用ORM的annotate和values做分组聚合from django.http import JsonResponse from django.db.models import Sum, Count from .models import Product, UserBehavior def brand_sales_api(request): # 获取品牌维度的聚合销量数据 data (UserBehavior.objects .filter(action_typebuy) .values(product__brand) .annotate(total_salesSum(score)) .order_by(-total_sales)[:10]) result [] for item in data: result.append({ brand: item[product__brand], sales: float(item[total_sales] or 0) }) return JsonResponse({code: 0, data: result})这里有个性能陷阱要注意如果不加缓存每次请求都会实时执行聚合SQL。大屏页面刚打开时多个接口同时请求数据库压力会瞬间拉高。我在前面说过要加缓存这里再补充一个具体做法——用Django的cache_page装饰器给这些API设置5到30分钟不等的缓存时间语法极简一行代码解决问题from django.views.decorators.cache import cache_page cache_page(60 * 30) # 缓存30分钟 def brand_sales_api(request): ...缓存命中时后端响应时间从几百毫秒降到十几毫秒大屏加载速度体验差异非常明显。5. Django系统集成与核心功能模块5.1 系统功能模块划分前面把采集、算法、可视化三条线分别拆开讲了现在把它们用Django整合成一个完整的Web应用。系统按角色划分大致有三个功能域普通用户端、运营管理端、系统支撑端。普通用户端包含注册登录、商品浏览、商品详情、个性化推荐列表、收藏夹、购物车下单流程。这一端面向C端用户是推荐算法的直接应用场景。运营管理端则服务管理员或运营人员核心功能是商品管理增删改查、用户管理、行为数据看板、推荐算法效果监控。Django自带的Admin后台可以覆盖大部分管理需求但为了让大屏数据展示更专业有必要单独做一版运营数据总览页也就是前面那套可视化大屏。系统支撑端包含定时任务数据更新、推荐结果重算、日志模块行为埋点、异常记录、缓存模块。这些模块不直接面对用户但决定了系统能跑多稳。模块划分清晰之后Django的App结构按功能域拆分apps/accounts——用户认证与个人中心apps/products——商品管理与检索apps/recommend——推荐算法与推荐结果接口apps/dashboard——大屏数据统计接口apps/orders——购物车与订单流程这样拆分的好处是各App职责单一代码之间耦合度低。比如后面要替换推荐算法只需要改recommend模块内部实现接口对外保持兼容即可。5.2 核心流程串联与关键代码系统最核心的用户操作路径是登录→浏览商品→产生行为→系统更新推荐→用户查看推荐列表→再次互动。这条闭环链路的打通直接决定了项目完成度。用户浏览商品时前端页面通过AJAX向后端提交行为日志// 商品详情页埋点 fetch(/api/behavior/log, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ product_id: productId, action_type: view, csrfmiddlewaretoken: getCookie(csrftoken) }) });后端接收并写入行为表同时触发一个异步任务更新该用户的推荐结果缓存。异步任务我用了Django的线程池简单处理没有引入Celery。毕设场景下Celery显得过重而且要在服务器上常驻Worker进程答辩演示时多一个故障点。线程池配合内存队列足以支撑演示规模下的实时推荐更新。推荐列表的展示接口如下def recommend_api(request): user request.user # 优先读缓存 cached cache.get(frec_{user.id}) if cached: return JsonResponse({code: 0, data: cached}) # 无缓存则调用推荐服务生成 rec_items ItemCFService().recommend(user.id, top_n10) cache.set(frec_{user.id}, rec_items, timeout600) return JsonResponse({code: 0, data: rec_items})前端拿到推荐商品ID列表后再根据ID查商品详情接口补齐封面图、价格、品牌等展示字段用卡片流渲染在页面中。推荐列表的每次刷新都按固定算法重排这既是产品功能也直接服务于课题中“协同过滤推荐算法的应用验证”这一目标。5.3 系统性能优化与部署要点代码写完之后部署和性能优化是很容易被毕设同学忽视的环节。实际上这个环节做得好不好直接影响答辩时的流畅度。Django默认的开发服务器runserver只能用于本机调试绝对不建议在答辩演示时直接暴露给多台设备访问。正确的开发方式是使用Django Gunicorn Nginx三层结构Gunicorn充当Python应用服务器Nginx负责静态文件服务和反向代理。Nginx处理静态资源图片、CSS、JS的效率远高于Django本身可以显著降低应用服务器压力。即使不买云服务器、只在本地跑演示也建议用Nginx做反向代理绑定80端口。这样浏览器访问时走的是标准HTTP流程比跑到8000端口显得专业得多。静态资源是另一个优化点。ECharts的min.js文件就有近1MB加上其他图表插件如果全部从Django静态目录加载首次打开页面会很慢。部署时用nginx的gzip on开启压缩可以把传输体积压缩到原来的30%左右。数据库层面需要给高频查询字段添加索引。行为表的user_id和product_id、商品表的brand和model_code都是查询频繁的字段。Django ORM中在模型字段设置db_indexTrue即可迁移后生效。索引对写入性能有一定损耗但在这个规模下几乎无感知。6. 大模型与Agent融合——给系统装上智能大脑6.1 AI能力的切入点标题里出现了大模型和agent关键词。这个项目目前已经具备了基础的数据积累和推荐能力但数据的呈现方式还停留在“图表和数字”的层面。用户可以自己看图表得出结论但如果让大模型自动分析数据并生成业务结论整个系统的智能化程度会上一个台阶。我规划了两个大模型融合的切入点。第一个是智能数据分析助手。它接收用户的自然语言查询比如“这个月哪个品牌的鞋销量增长最快”系统将查询转换为SQL或数据查询逻辑从数据库取数后用大模型生成结论和图表参数直接返回给前端渲染。这个能力本质上是一个轻量级的Text-to-SQL加自然语言生成方案。第二个是智能商品推荐解说。协同过滤算法给出推荐列表后大模型根据商品特征、价格、品牌为每个推荐商品生成一段推荐理由让用户明白“为什么推荐这双鞋”而不是干巴巴地展示一个商品卡片。6.2 技术选型与实现思路在具体选型上考虑到毕设环境和成本控制优先选择国内可稳定访问的大模型API。调用方式统一走HTTP接口模型本身不需要本地部署——毕设阶段完全没有必要在本地跑一个几百GB的模型权重调用云端API的稳定性远高于本地推理。智能数据分析助手的实现思路是构建一个Agent流程解析用户输入的自然语言查询意图识别实体和时间范围将解析结果映射为数据库查询优先使用预定义的SQL模板利用LLM的SQL生成能力处理模板之外的查询执行查询获取结构化数据将查询结果压缩成上下文片段交给大模型生成结论性描述返回结论文本和可选的图表配置给前端展示。import requests import json def llm_analyze(question): # 将用户问题与数据摘要组装成Prompt prompt f 你是一名鞋类电商数据分析师。基于以下销售统计数据进行回答。 数据摘要 {get_data_summary()} 用户问题{question} 请给出具体结论引用关键数字不超过150字。 resp requests.post( https://api.example.com/v1/chat/completions, headers{Authorization: Bearer api_key}, json{ model: model-name, messages: [{role: user, content: prompt}], temperature: 0.3, max_tokens: 300 }, timeout15 ) result json.loads(resp.text) return result[choices][0][message][content]这里有一个关键技巧不要把整个数据库的直接查询权限暴露给大模型而是给它一个数据摘要让它基于摘要做分析。数据库原始表包含用户隐私和行为细节全部暴露给外部模型存在数据安全风险。将数据先聚合成指标再交给模型推理既安全又能保证输出的业务相关性。系统对这个方案做了兜底Agent在判定自己无法回答时设计回退到查询推荐接口或多轮追问机制不会返回无意义的乱码。另外在prompt中特别强化了“只基于提供的数据回答不要编造数据”的约束避免大模型出现幻觉。6.3 融合效果验收与挑战Agent能力上线后如何验证效果关乎结论的可靠性。我设置了三个验证层面。准确性层面给大模型生成的分析结论配数据来源即结论底部标注“数据来源近30天品牌销量统计”答辩和抽查时可以直接回溯验证。对于建模准确性要求高的场景明确提示大模型“如果数据不足请指出数据局限”。安全性层面对用户输入做LLM注入防护防止用户通过构造提示词绕过系统限制获取不应该展示的数据内容。基础的输入过滤加上输出限制可以挡住大部分常见攻击。稳定性层面大模型API的响应时间通常在2到10秒之间明显慢于传统接口。交互上采用“流式输出”的方式实时显示分析进度避免用户等待时误以为页面卡死。同时设置异常重试机制API调用失败时自动降级为模板化结论。这一块把agent能力作为“增强项”来写。数据推荐与协同过滤才是系统的核心大模型只是锦上添花。如果答辩时间紧张也可以一句话带过不影响主体逻辑的完整性。7. 常见问题与避坑指南实录7.1 高频问题排查速查表项目开发过程中我遇到并解决的典型问题非常有代表性遇到相同报错的概率很大。问题现象根因分析解决思路pip安装Django超时或失败默认源在国外网络不稳换清华或阿里镜像源pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple迁移时报错字段冲突修改模型字段未做迁移删除迁移文件和旧数据库重新执行makemigrations中文乱码数据库编码不是utf8mb4建库时指定CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ciECharts图表不显示JavaScript报错或容器宽高为0给图表容器设置固定高度在resize事件中调用chart.resize()推荐列表为空用户无行为数据或相似度未计算触发一次离线全量重算冷启动用户返回热门榜大屏接口响应慢未加缓存实时查库cache_page装饰器缓存300秒大模型返回空字符串上下文token超限或触发风控缩短摘要长度控制prompt在800字以内7.2 我的踩坑记录与实操心得先说一个大坑Python版本兼容性。Django 4和5系列对Python版本有严格要求Django 4.2支持Python 3.8到3.11Django 5.0则需要Python 3.10到3.12。如果你机器上是Python 3.7直接pip install django会安装最新版然后报错。建议在项目目录用python -m venv venv创建虚拟环境在虚拟环境中安装Django彻底避免系统全局环境被污染。开发过程中换了三个版本的依赖库也没出现兼容性问题虚拟环境省了我大量返工时间。第二个坑是MySQL版本和服务名不一致。Windows上安装MySQL后服务名可能是MySQL80但默认的my.ini中配置的socket路径不对导致Django报Cant connect to MySQL server。解决方法是确认服务是否启动用mysql -u root -p手动连接一次再把Django数据库配置的HOST从localhost换成127.0.0.1端口保持3306。第三个坑来自Pandas和Django的共用陷阱。Pandas的DataFrame.to_sql写数据默认会要求表的主键存在如果目标表没建主键或者字段类型不匹配会直接报错。我的做法是先用Django迁移建好表再在Pandas中用if_existsappend跳过建表逻辑。关于ECharts新手最容易犯的错误是为了做动态更新而频繁用setOption导致动画闪烁卡顿。正确的做法是首次渲染用setOption传入完整配置后续更新只传入改变的数据字段并用notMerge参数控制合并方式。这个细节在答辩演示时如果被问到解释清楚会显得很专业。7.3 项目扩展方向与二次开发建议做完这套系统它的“生命周期”其实才刚刚开始。我可以给你几个明确的扩展方向。推荐算法升级方向从ItemCF进阶到矩阵分解SVD或图神经网络推荐。SVD能捕获用户和商品的隐向量表示推荐效果通常比协同过滤提升一个档次。代码改动量适中论文中可以做新旧算法效果对比这是很受指导老师认可的章节。数据分析深度方向加入销量预测模块用时间序列模型对未来30天鞋类整体销量做预测。ARIMA和Prophet都有现成药丸式实现接入大屏的预测曲线后数据可视化维度从“看历史”升级为“看未来”。Agent深化方向把大模型分析从被动问答升级为主动监控——每天定时读取销售数据生成运营日报文本并把异常波动点标记出来。这本质上一个自动化的数据巡检Agent代码量不大但展示时非常惊艳。从内容上讲目前该项目的核心链路是数据采集→数据治理→协同过滤→数据可视化→AI增强。每个环节在业界都有对应的工程实践和完整方法论这套系统是一个微缩版的企业数据应用原型。所以把它说成“毕业设计源码”低估了它的价值——我更愿意把它看成是个人数据产品的MVP。这也是整个项目最有价值的地方它是一个全景式的工程实践覆盖了数据分析与推荐系统的完整生命周期。
返回列表