1. 项目概述与技术选型
这个基于协同过滤算法的智能推荐购物平台项目,是我在指导计算机专业毕业设计过程中反复打磨的一个典型案例。它完整覆盖了从数据采集、算法实现到前后端开发的电商系统全流程,特别适合作为全栈开发的学习项目。
为什么选择这个技术栈组合?经过多年项目实践,我发现Python+Django+Vue3的组合在中小型电商系统中具有显著优势:
- Django自带强大的ORM和Admin后台,能快速构建数据模型和管理界面
- Vue3的Composition API让前端组件开发更灵活高效
- Python生态中的Scrapy框架是爬虫开发的不二之选
- 协同过滤算法在推荐系统入门阶段实现成本最低但效果显著
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 前后端分离架构
项目采用典型的前后端分离架构:
code复制前端层:Vue3 + Vite + Element Plus
↑
HTTP API (JSON)
↓
后端层:Django REST Framework
↑
数据层:MySQL + Redis缓存
这种架构的优势在于:
- 前后端可以并行开发,通过API文档约定接口规范
- 前端可以使用更现代的构建工具和组件库
- 后端专注业务逻辑,不需要处理模板渲染
2.2 数据库设计
核心的MySQL表结构设计如下(简化版):
sql复制CREATE TABLE `product` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`price` decimal(10,2) NOT NULL,
`cat1` varchar(50) COMMENT '一级分类',
`cat2` varchar(50) COMMENT '二级分类',
`cat3` varchar(50) COMMENT '三级分类',
`sales` int DEFAULT '0' COMMENT '销量',
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `product_history` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`product_id` int NOT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB;
注意:实际项目中密码字段应该使用Django的make_password加密存储,这里为简化展示使用明文
3. 核心功能实现
3.1 商品数据采集
使用Scrapy爬虫采集商品数据的核心代码:
python复制import scrapy
class ProductSpider(scrapy.Spider):
name = 'jd_spider'
def start_requests(self):
urls = ['https://list.jd.com/list.html?cat=9987,653,655']
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
for item in response.css('.gl-item'):
yield {
'name': item.css('.p-name em::text').get().strip(),
'price': float(item.css('.p-price i::text').get()),
'cat1': '手机',
'cat2': '智能手机',
'cat3': '5G手机'
}
next_page = response.css('.pn-next::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)
爬虫设计要点:
- 使用CSS选择器定位元素比XPath更易读
- 分页处理要检查下一页按钮是否存在
- 数据清洗应该在pipeline中完成
3.2 协同过滤推荐算法
基于用户的协同过滤算法实现:
python复制from collections import defaultdict
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
def collaborative_filtering(user_id, top_n=5):
# 获取所有用户历史记录
histories = ProductHistory.objects.all()
# 构建用户-商品矩阵
user_items = defaultdict(set)
for h in histories:
user_items[h.user_id].add(h.product_id)
# 计算用户相似度
all_users = list(user_items.keys())
sim_matrix = np.zeros((len(all_users), len(all_users)))
for i, u1 in enumerate(all_users):
for j, u2 in enumerate(all_users):
if i <= j:
set1 = user_items[u1]
set2 = user_items[u2]
intersection = len(set1 & set2)
union = len(set1 | set2)
sim = intersection / union if union else 0
sim_matrix[i][j] = sim
sim_matrix[j][i] = sim
# 找到最相似的K个用户
user_idx = all_users.index(user_id)
similar_users = np.argsort(-sim_matrix[user_idx])[1:6] # 排除自己
# 合并相似用户的商品
recommend_items = set()
for idx in similar_users:
recommend_items.update(user_items[all_users[idx]])
# 排除已购买商品
user_own = user_items[user_id]
recommend_items -= user_own
# 返回推荐商品
return Product.objects.filter(id__in=list(recommend_items))[:top_n]
算法优化点:
- 使用Jaccard相似度计算用户相似性
- 引入权重机制(浏览、购买、收藏不同权重)
- 对稀疏矩阵使用稀疏存储优化
4. 关键业务逻辑实现
4.1 商品列表API
Django视图函数示例:
python复制from django.core.paginator import Paginator
from django.db.models import Q
def product_list(request):
# 获取查询参数
page = int(request.GET.get('page', 1))
size = int(request.GET.get('size', 10))
keyword = request.GET.get('keyword', '')
cat1 = request.GET.get('cat1', '')
# 构建查询条件
q = Q(is_active=True)
if keyword:
q &= Q(name__icontains=keyword)
if cat1:
q &= Q(cat1=cat1)
# 分页查询
queryset = Product.objects.filter(q).order_by('-sales')
paginator = Paginator(queryset, size)
# 序列化结果
products = []
for p in paginator.page(page):
products.append({
'id': p.id,
'name': p.name,
'price': float(p.price),
'image': p.image.url if p.image else ''
})
return JsonResponse({
'total': paginator.count,
'products': products
})
4.2 购物车功能
前端Vue3实现购物车逻辑:
javascript复制import { ref, computed } from 'vue'
import { useStore } from 'vuex'
export function useCart() {
const store = useStore()
// 购物车商品
const cartItems = computed(() => store.state.cart.items)
// 总金额
const totalAmount = computed(() => {
return cartItems.value.reduce((sum, item) => {
return sum + (item.price * item.quantity)
}, 0)
})
// 添加商品
const addToCart = (product) => {
store.commit('cart/addItem', {
id: product.id,
name: product.name,
price: product.price,
image: product.image,
quantity: 1
})
}
// 更新数量
const updateQuantity = (id, quantity) => {
if (quantity <= 0) {
store.commit('cart/removeItem', id)
} else {
store.commit('cart/updateQuantity', { id, quantity })
}
}
return {
cartItems,
totalAmount,
addToCart,
updateQuantity
}
}
5. 项目部署与优化
5.1 生产环境部署
推荐使用Docker Compose部署:
dockerfile复制# docker-compose.yml
version: '3'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: shop
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./backend
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./backend:/code
ports:
- "8000:8000"
depends_on:
- db
frontend:
build: ./frontend
command: npm run serve
volumes:
- ./frontend:/app
ports:
- "8080:8080"
volumes:
mysql_data:
5.2 性能优化建议
-
数据库优化:
- 为常用查询字段添加索引
- 使用select_related/prefetch_related减少查询次数
- 引入Redis缓存热门商品数据
-
前端优化:
- 使用Vue的keep-alive缓存组件
- 实现图片懒加载
- 按需加载第三方库
-
推荐算法优化:
- 离线计算用户相似度矩阵
- 使用Celery异步任务更新推荐结果
- 引入混合推荐策略(结合内容推荐)
6. 常见问题与解决方案
6.1 跨域问题
Django后端配置CORS:
python复制# settings.py
INSTALLED_APPS = [
...,
'corsheaders'
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
]
CORS_ORIGIN_WHITELIST = [
'http://localhost:8080',
'http://127.0.0.1:8080'
]
6.2 推荐效果不佳
提升推荐质量的几种方法:
-
数据层面:
- 收集更多用户行为数据(浏览时长、滚动深度等)
- 引入显式反馈(评分、点赞)
-
算法层面:
- 尝试基于物品的协同过滤
- 引入时间衰减因子(新行为权重更高)
- 使用矩阵分解等高级技术
-
工程层面:
- 实现A/B测试框架
- 建立推荐效果评估指标(点击率、转化率)
6.3 爬虫被封禁
反反爬虫策略:
-
基础措施:
- 设置合理的下载延迟(DOWNLOAD_DELAY)
- 使用随机User-Agent
- 启用自动限速扩展
-
高级方案:
- 使用代理IP池
- 实现验证码识别
- 模拟浏览器行为(Selenium)
7. 项目扩展方向
这个基础项目可以进一步扩展为:
-
移动端适配:
- 使用Vant或NutUI构建移动端组件
- 开发微信小程序版本
-
大数据分析:
- 集成Hadoop/Spark处理用户行为日志
- 使用Flink实现实时推荐
-
智能客服:
- 接入大模型API实现智能问答
- 构建商品知识图谱
-
营销系统:
- 实现优惠券发放引擎
- 开发拼团/秒杀模块
这个项目最让我有成就感的是看到学生通过它掌握了全栈开发的核心技能。在实际教学中,我会建议学生先实现基础功能,再选择1-2个方向进行深度扩展,这样的学习效果最好。
