from flask import Flask, render_template, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
import numpy as np
import random
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ecommerce.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# 模型定义
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(200), nullable=False)
description = db.Column(db.Text)
price = db.Column(db.Float, nullable=False)
category = db.Column(db.String(100))
brand = db.Column(db.String(100))
image_url = db.Column(db.String(200))
rating = db.Column(db.Float)
reviews_count = db.Column(db.Integer)
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'price': self.price,
'image_url': self.image_url,
'category': self.category,
'brand': self.brand
}
class UserBehavior(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
action = db.Column(db.String(20), nullable=False) # 'view', 'search', 'buy', 'add_to_cart'
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
class SearchHistory(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
query = db.Column(db.String(200), nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
# 搜索建议API - 基于协同过滤
@app.route('/api/suggestions', methods=['GET'])
def get_suggestions():
query = request.args.get('query', '').strip().lower()
user_id = request.args.get('user_id', 1, type=int) # 实际项目中应从会话获取
if len(query) < 2:
return jsonify([])
# 1. 基于内容的搜索建议
content_based_suggestions = get_content_based_suggestions(query)
# 2. 基于协同过滤的搜索建议
collaborative_suggestions = get_collaborative_filtering_suggestions(user_id, query)
# 3. 基于用户历史的搜索建议
# history_suggestions = get_history_based_suggestions(user_id, query)
# 合并结果并去重
suggestions = []
suggestion_set = set()
# 优先添加协同过滤建议
for suggestion in collaborative_suggestions:
if suggestion['value'].lower() not in suggestion_set:
suggestion_set.add(suggestion['value'].lower())
suggestions.append(suggestion)
# 添加内容建议
for suggestion in content_based_suggestions:
if suggestion['value'].lower() not in suggestion_set:
suggestion_set.add(suggestion['value'].lower())
suggestions.append(suggestion)
# # 添加历史建议
# for suggestion in history_suggestions:
# if suggestion['value'].lower() not in suggestion_set:
# suggestion_set.add(suggestion['value'].lower())
# suggestions.append(suggestion)
return jsonify(suggestions[:5])
# 基于内容的搜索建议
def get_content_based_suggestions(query):
products = Product.query.filter(
(Product.name.ilike(f'%{query}%')) |
(Product.description.ilike(f'%{query}%'))
).limit(5).all()
return [
{
'type': 'product',
'value': product.name,
'data': product.to_dict()
}
for product in products
]
# 基于协同过滤的搜索建议
def get_collaborative_filtering_suggestions(user_id, query):
# 获取用户最近的行为
recent_behaviors = UserBehavior.query.filter(
UserBehavior.user_id == user_id
).order_by(UserBehavior.timestamp.desc()).limit(10).all()
if not recent_behaviors:
return []
# 获取相似用户喜欢的商品
similar_user_products = get_similar_users_products(user_id)
# 从相似用户喜欢的商品中筛选与查询相关的
relevant_products = []
for product in similar_user_products:
if query.lower() in product.name.lower() or query.lower() in (product.description or '').lower():
relevant_products.append(product)
return [
{
'type': 'collaborative',
'value': product.name,
'data': product.to_dict()
}
for product in relevant_products[:3]
]
# 获取相似用户喜欢的商品
def get_similar_users_products(user_id):
# 这里实现协同过滤算法
# 获取所有用户行为数据
behaviors = UserBehavior.query.all()
# 构建用户-商品交互矩阵
user_item_matrix = {}
for behavior in behaviors:
if behavior.user_id not in user_item_matrix:
user_item_matrix[behavior.user_id] = {}
# 不同行为赋予不同权重
if behavior.action == 'buy':
weight = 3
elif behavior.action == 'add_to_cart':
weight = 2
elif behavior.action == 'view':
weight = 1
else: # search
weight = 1.5
user_item_matrix[behavior.user_id][behavior.product_id] = weight
# 如果没有足够的数据,返回热门商品
if len(user_item_matrix) < 2 or user_id not in user_item_matrix:
return Product.query.order_by(Product.reviews_count.desc()).limit(5).all()
# 计算当前用户与其他用户的相似度
target_user = user_item_matrix[user_id]
similarities = []
for other_user_id, items in user_item_matrix.items():
if other_user_id == user_id:
continue
# 计算余弦相似度
dot_product = 0
target_norm = 0
other_norm = 0
for item_id, weight in items.items():
if item_id in target_user:
dot_product += target_user[item_id] * weight
other_norm += weight ** 2
for item_id, weight in target_user.items():
target_norm += weight ** 2
if target_norm == 0 or other_norm == 0:
similarity = 0
else:
similarity = dot_product / (np.sqrt(target_norm) * np.sqrt(other_norm))
similarities.append((other_user_id, similarity))
# 按相似度排序
similarities.sort(key=lambda x: x[1], reverse=True)
# 获取最相似的前3个用户
top_similar_users = similarities[:3]
# 从相似用户喜欢的商品中推荐
recommended_products = set()
for similar_user_id, _ in top_similar_users:
for product_id in user_item_matrix[similar_user_id]:
if product_id not in target_user:
product = Product.query.get(product_id)
if product:
recommended_products.add(product)
return list(recommended_products)
# 基于用户历史的搜索建议
def get_history_based_suggestions(user_id, query):
history_suggestions = SearchHistory.query.filter(
SearchHistory.user_id == user_id,
SearchHistory.query.ilike(f'%{query}%')
).order_by(SearchHistory.timestamp.desc()).limit(3).all()
return [
{
'type': 'history',
'value': history.query,
'data': {'query': history.query}
}
for history in history_suggestions
]
# 搜索功能
@app.route('/search', methods=['GET'])
def search():
query = request.args.get('query', '')
category = request.args.get('category')
brand = request.args.get('brand')
min_price = request.args.get('min_price', type=float)
max_price = request.args.get('max_price', type=float)
# 记录搜索历史
user_id = 1 # 假设已登录用户
if query:
search_history = SearchHistory(user_id=user_id, query=query)
db.session.add(search_history)
# 记录用户搜索行为
products = Product.query.filter(
(Product.name.ilike(f'%{query}%')) |
(Product.description.ilike(f'%{query}%'))
).limit(3).all()
for product in products:
behavior = UserBehavior(
user_id=user_id,
product_id=product.id,
action='search'
)
db.session.add(behavior)
db.session.commit()
# 执行搜索
products = search_products(query, category, brand, min_price, max_price)
return render_template('search_results.html', products=products, query=query)
# 搜索商品的辅助函数
def search_products(query, category=None, brand=None, min_price=None, max_price=None):
query = query.strip()
base_query = Product.query
if query:
base_query = base_query.filter(
(Product.name.ilike(f'%{query}%')) |
(Product.description.ilike(f'%{query}%'))
)
if category:
base_query = base_query.filter(Product.category == category)
if brand:
base_query = base_query.filter(Product.brand == brand)
if min_price is not None:
base_query = base_query.filter(Product.price >= min_price)
if max_price is not None:
base_query = base_query.filter(Product.price <= max_price)
# 按相关性和销量排序
return base_query.order_by(Product.reviews_count.desc()).all()
# 首页
@app.route('/')
def index():
# 获取热门商品
trending_products = Product.query.order_by(Product.reviews_count.desc()).limit(8).all()
# 获取推荐商品
user_id = 1 # 假设已登录用户
user_recs = get_user_recommendations(user_id)
return render_template('base.html', trending=trending_products, user_recs=user_recs)
# 获取用户推荐
def get_user_recommendations(user_id):
# 使用协同过滤获取推荐商品
recommended_products = get_similar_users_products(user_id)
# 如果推荐不足,补充热门商品
if len(recommended_products) < 4:
hot_products = Product.query.order_by(Product.reviews_count.desc()).all()
for product in hot_products:
if product not in recommended_products:
recommended_products.append(product)
if len(recommended_products) >= 4:
break
return recommended_products[:4]
# 初始化示例数据
def init_sample_data():
if Product.query.count() == 0:
# 添加示例产品
sample_products = [
{
'name': '苹果 iPhone 14 Pro 256GB',
'description': '6.1英寸超视网膜XDR显示屏,A16仿生芯片,4800万像素主摄',
'price': 7999.0,
'category': '手机',
'brand': '苹果',
'image_url': 'https://picsum.photos/seed/iphone14/400/400',
'rating': 4.8,
'reviews_count': 1204
},
{
'name': '华为 Mate 50 Pro 256GB',
'description': '6.74英寸OLED屏幕,骁龙8+ 4G芯片,超光变摄像头苹果',
'price': 6799.0,
'category': '手机',
'brand': '华为',
'image_url': 'https://picsum.photos/seed/mate50/400/400',
'rating': 4.7,
'reviews_count': 987
},
{
'name': '小米 13 Pro 256GB',
'description': '6.73英寸2K屏幕,骁龙8 Gen2芯片,徕卡三摄',
'price': 5999.0,
'category': '手机',
'brand': '小米',
'image_url': 'https://picsum.photos/seed/xiaomi13/400/400',
'rating': 4.6,
'reviews_count': 856
},
{
'name': '三星 Galaxy S23 Ultra 256GB',
'description': '6.8英寸2K AMOLED屏幕,骁龙8 Gen2芯片,2亿像素主摄',
'price': 8999.0,
'category': '手机',
'brand': '三星',
'image_url': 'https://picsum.photos/seed/s23ultra/400/400',
'rating': 4.7,
'reviews_count': 732
},
{
'name': 'Apple Watch Series 8',
'description': '45毫米铝金属表壳,全天候视网膜显示屏,血氧检测',
'price': 3199.0,
'category': '智能手表',
'brand': '苹果',
'image_url': 'https://picsum.photos/seed/aw8/400/400',
'rating': 4.6,
'reviews_count': 1120
},
{
'name': '华为 Watch GT 3 Pro',
'description': '46毫米钛金属表壳,圆形屏幕,精准心率监测',
'price': 2499.0,
'category': '智能手表',
'brand': '华为',
'image_url': 'https://picsum.photos/seed/gt3pro/400/400',
'rating': 4.5,
'reviews_count': 980
},
{
'name': '小米 Watch S1 Pro',
'description': '1.43英寸AMOLED屏幕,117种运动模式,50米防水',
'price': 1299.0,
'category': '智能手表',
'brand': '小米',
'image_url': 'https://picsum.photos/seed/miw1/400/400',
'rating': 4.4,
'reviews_count': 760
},
{
'name': 'AirPods Pro 2',
'description': '主动降噪,通透模式,自适应均衡,IP54防水防尘',
'price': 1899.0,
'category': '耳机',
'brand': '苹果',
'image_url': 'https://picsum.photos/seed/airpods2/400/400',
'rating': 4.7,
'reviews_count': 1540
},
{
'name': '华为 FreeBuds Pro 2',
'description': '主动降噪,高解析度音频,双单元设计',
'price': 1199.0,
'category': '耳机',
'brand': '华为',
'image_url': 'https://picsum.photos/seed/hwbuds2/400/400',
'rating': 4.6,
'reviews_count': 1230
},
{
'name': '小米 Buds 4 Pro',
'description': '主动降噪,HiFi音质,通透模式,无线充电',
'price': 799.0,
'category': '耳机',
'brand': '小米',
'image_url': 'https://picsum.photos/seed/xmbuds4/400/400',
'rating': 4.5,
'reviews_count': 980
}
]
for product_data in sample_products:
product = Product(**product_data)
db.session.add(product)
db.session.commit()
# 添加示例用户
user = User(username='test_user', email='test@example.com')
db.session.add(user)
db.session.commit()
# 添加示例用户行为
user_id = user.id
product_ids = [p.id for p in Product.query.all()]
# 用户1的行为
for i, product_id in enumerate(product_ids[:5]):
actions = ['view', 'search', 'add_to_cart', 'buy', 'view']
for action in actions:
behavior = UserBehavior(
user_id=user_id,
product_id=product_id,
action=action
)
db.session.add(behavior)
# 添加一些其他用户的行为,用于协同过滤
for other_user_id in range(2, 6):
other_user = User(username=f'user{other_user_id}', email=f'user{other_user_id}@example.com')
db.session.add(other_user)
db.session.commit()
# 每个用户随机喜欢一些商品
liked_products = random.sample(product_ids, random.randint(3, 6))
for product_id in liked_products:
action = random.choice(['view', 'add_to_cart', 'buy'])
behavior = UserBehavior(
user_id=other_user_id,
product_id=product_id,
action=action
)
db.session.add(behavior)
db.session.commit()
if __name__ == '__main__':
with app.app_context():
db.create_all()
# 初始化一些示例数据
init_sample_data()
app.run(debug=True)
这是代码 需要改什么吗