1. 项目概述与设计思路
这个基于Django框架的双协同过滤推荐电商系统,是我在指导计算机专业毕业设计时开发的一个典型项目案例。系统核心解决了电商平台中普遍存在的两个痛点:商品信息过载导致的用户选择困难,以及静态推荐带来的个性化体验不足问题。
项目采用经典的MVC架构设计,主要分为以下几个层次:
- 数据层:使用MySQL存储商品信息、用户数据和行为记录
- 算法层:实现基于用户和基于物品的双协同过滤推荐算法
- 业务层:Django框架处理核心业务逻辑和流程控制
- 表现层:HTML模板渲染前端界面,实现用户交互
在技术选型上,我们选择了Django而非Flask,主要基于以下考虑:
- Django自带完善的ORM、Admin后台和认证系统,能快速搭建起电商系统的基础框架
- Django的MTV模式天然适合推荐系统这类数据密集型应用
- 社区生态完善,遇到问题更容易找到解决方案
- 自带的安全防护机制(CSRF、XSS防护等)对电商系统尤为重要
提示:对于毕业设计项目,建议优先选择Django而非Flask,因为Django的"全包含"特性可以让你把更多精力放在核心算法实现上,而不是重复造轮子。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心模块实现细节
2.1 用户认证模块
用户模块采用Django内置的auth系统进行扩展,主要实现了以下功能:
python复制# account/models.py
from django.contrib.auth.models import AbstractUser
class Account(AbstractUser):
phone = models.CharField(max_length=11, blank=True)
avatar = models.ImageField(upload_to='avatar/', default='avatar/default.png')
class Meta:
verbose_name = '用户账号'
verbose_name_plural = verbose_name
关键实现要点:
- 继承AbstractUser而不是从头实现用户模型
- 添加了手机号和头像两个扩展字段
- 使用Django的session机制保持登录状态
- 密码采用PBKDF2算法加密存储
在视图层,我们重写了登录逻辑,增加了行为数据采集:
python复制# account/views.py
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user:
login(request, user)
# 记录登录行为
UserBehavior.objects.create(
user=user,
behavior_type='login',
content='用户登录系统'
)
return redirect('index')
2.2 双协同过滤算法实现
系统核心创新点在于实现了基于用户和基于物品的双协同过滤算法。以下是基于物品的协同过滤实现:
python复制class ItemCF:
def __init__(self, data):
self.similar = dict()
self.data = data
def item_similarity(self):
# 建立物品-物品共现矩阵
cooccur = dict()
buy = dict()
for user, items in self.data.items():
for i in items.keys():
buy.setdefault(i, 0)
buy[i] += 1
cooccur.setdefault(i, {})
for j in items.keys():
if i == j: continue
cooccur[i].setdefault(j, 0)
cooccur[i][j] += 1
# 计算相似度矩阵
for i, related_items in cooccur.items():
self.similar.setdefault(i, {})
for j, cij in related_items.items():
self.similar[i][j] = cij / (math.sqrt(buy[i] * buy[j]))
return self.similar
算法选择考虑:
- 基于用户的CF更适合用户量大的场景
- 基于物品的CF在商品相对稳定的情况下效果更好
- 两种算法结合可以优势互补,提高推荐质量
在实际应用中,我们设置了算法权重调节机制:
python复制# 在settings.py中配置
RECOMMEND_ALGORITHM_WEIGHTS = {
'user_cf': 0.6,
'item_cf': 0.4
}
2.3 数据爬虫模块
数据采集使用requests库实现,主要流程包括:
- 目标网站分析(商品列表页、详情页结构)
- 请求头伪装(User-Agent、Referer等)
- 页面解析(BeautifulSoup/lxml)
- 数据清洗存储
核心爬虫类实现:
python复制class ProductSpider:
def __init__(self, keyword):
self.keyword = keyword
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
def parse_list_page(self, url):
try:
resp = self.session.get(url, timeout=10)
soup = BeautifulSoup(resp.text, 'lxml')
items = soup.select('.product-item')
for item in items:
product = {
'title': item.select('.title')[0].text.strip(),
'price': float(item.select('.price')[0].text[1:]),
'image': item.select('img')[0]['src']
}
yield product
except Exception as e:
logging.error(f"爬取列表页失败: {str(e)}")
注意:实际项目中需要遵守robots协议,控制爬取频率,建议设置2-3秒的延迟,避免对目标网站造成过大压力。
3. 系统优化与实践经验
3.1 性能优化方案
在项目开发过程中,我们遇到了几个性能瓶颈及解决方案:
- 推荐算法计算耗时问题:
- 实现离线计算:每天凌晨计算好推荐结果存入缓存
- 使用django-cacheops缓存相似度矩阵
- 对活跃用户实施实时计算,普通用户使用缓存结果
- 数据库查询优化:
python复制# 优化前
products = Product.objects.filter(id__in=id_list)
# 优化后
products = Product.objects.filter(id__in=id_list).select_related('category').prefetch_related('tags')
- 前端性能优化:
- 使用django-compressor压缩静态资源
- 实现懒加载商品图片
- 对API响应启用Gzip压缩
3.2 推荐算法效果提升技巧
通过实际项目运行,我们总结出以下提升推荐效果的经验:
- 数据冷启动解决方案:
- 新用户:采用"热门商品+随机推荐"策略
- 新商品:给予一定的曝光加权
- 实现简单的基于内容的推荐作为补充
- 行为权重设计:
python复制BEHAVIOR_WEIGHTS = {
'view': 1, # 浏览
'collect': 3, # 收藏
'buy': 5 # 购买
}
- 时间衰减因子:
python复制def get_time_decay(behavior_time):
delta = datetime.now() - behavior_time
return 1 / (1 + delta.days * 0.1) # 每天衰减10%
3.3 项目部署实践
系统采用Nginx+Gunicorn方案部署,关键配置如下:
- Gunicorn启动脚本:
bash复制#!/bin/bash
gunicorn ecommerce.wsgi:application \
--bind 0.0.0.0:8000 \
--workers 4 \
--threads 2 \
--timeout 120 \
--access-logfile - \
--error-logfile -
- Nginx配置要点:
nginx复制location /static/ {
alias /path/to/static/;
expires 30d;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
- 定时任务配置(Celery+Redis):
python复制@app.task
def daily_recommend_update():
# 更新用户相似度矩阵
update_user_similarity.delay()
# 更新物品相似度矩阵
update_item_similarity.delay()
4. 常见问题与解决方案
4.1 算法实现问题
Q1:协同过滤算法中的稀疏矩阵如何处理?
A1:我们采用了以下几种策略:
- 使用稀疏矩阵存储结构(scipy.sparse)
- 设置最小共同评分用户数阈值(如5)
- 引入默认评分(全局平均分)
Q2:如何解决推荐结果过于集中(热门商品)的问题?
A2:在推荐公式中加入流行度惩罚因子:
python复制def popularity_penalty(item_id, alpha=0.5):
popularity = get_item_popularity(item_id) # 获取商品热度
return 1 / (popularity ** alpha)
4.2 系统运行问题
Q3:用户量增大后系统响应变慢怎么办?
A3:我们采取的优化措施包括:
- 数据库层面:
- 添加合适的索引(用户行为表)
- 读写分离(主从复制)
- 查询优化(避免N+1问题)
- 缓存策略:
- 使用Redis缓存热门推荐结果
- 实现多级缓存(本地+分布式)
Q4:如何评估推荐算法效果?
A4:我们实现了几个评估指标:
- 离线指标:
- 准确率(Precision)
- 召回率(Recall)
- 覆盖率(Coverage)
- 在线指标:
- 点击率(CTR)
- 转化率(Conversion Rate)
- 平均停留时长
4.3 开发调试技巧
Q5:Django开发中有哪些实用的调试方法?
A5:推荐以下几种实践:
- 使用django-debug-toolbar分析查询
- 配置logging记录完整执行流程:
python复制LOGGING = {
'version': 1,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': 'debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
},
},
}
- 编写单元测试覆盖核心功能:
python复制class RecommendationTest(TestCase):
def setUp(self):
self.user = Account.objects.create(username='test')
def test_item_cf(self):
# 构造测试数据
# 调用推荐函数
# 断言结果
pass
在实际项目开发中,我们发现良好的日志记录和单元测试能节省大量调试时间,特别是在算法模块这种逻辑复杂的部分。
