1. 项目概述
这个美食推荐系统是我去年为一个本地餐饮联盟开发的实际项目,核心目标是通过数据分析帮助用户发现符合个人口味偏好的餐厅和菜品。系统采用Python+Django全栈开发,整合了网络爬虫、推荐算法和数据可视化三大模块,最终实现了从数据采集到个性化推荐的全流程自动化。
提示:在商业场景中,这类系统通常能提升30%以上的用户留存率和15%的订单转化率,关键在于推荐准确率和交互体验的平衡。
系统最核心的价值在于:
- 对用户:告别选择困难症,通过历史行为数据智能匹配相似口味用户喜欢的餐厅
- 对商家:精准触达目标客群,通过可视化报表掌握区域竞争态势
- 对运营方:建立餐饮数据中台,为后续的会员营销、优惠券发放提供数据支撑
技术选型上,Django框架提供了完善的后台管理和用户认证体系,Requests+BeautifulSoup组合保障了爬虫的稳定高效,而协同过滤算法则平衡了推荐准确度和计算效率。可视化部分采用Echarts而非更复杂的D3.js,主要考虑开发效率和移动端兼容性。
2. 技术架构解析
2.1 系统分层设计
整个系统采用经典的三层架构:
code复制表示层(Django模板)
↓
业务逻辑层(Views+算法)
↓
数据层(Models+爬虫)
每层的技术实现要点:
-
数据采集层
- 爬虫调度器:Celery定时任务
- 反爬策略:随机User-Agent + IP代理池
- 数据清洗:正则表达式去噪
- 存储方案:MySQL主表 + MongoDB存储评论原文
-
算法层
- 特征工程:菜品评分(1-5星) + 消费价格区间 + 地理位置
- 相似度计算:欧式距离标准化
- 冷启动方案:基于地域的热门榜单
-
展示层
- 响应式布局:Bootstrap 5
- 可视化渲染:Echarts 5
- 交互优化:Ajax局部刷新
2.2 核心算法实现
协同过滤算法的Python实现有几个关键优化点:
python复制def Euclidean(self, user1, user2):
# 权重调整:高评分菜品更具参考价值
weight = {5:1.2, 4:1.1, 3:1.0, 2:0.8, 1:0.5}
user1_data = self.data[user1]
user2_data = self.data[user2]
distance = 0
common_items = set(user1_data.keys()) & set(user2_data.keys())
# 只计算共同评分超过5个的用户
if len(common_items) < 5:
return 0
for item in common_items:
score1 = float(user1_data[item])
score2 = float(user2_data[item])
distance += pow((score1 - score2) * weight[score1], 2)
return 1 / (1 + sqrt(distance))
这段代码做了三处重要改进:
- 引入评分权重系数,5星评分的差异对相似度影响更大
- 设置共同评分阈值,避免数据稀疏导致的误判
- 使用集合运算加速共同菜品查找
实际测试显示,这些优化使推荐准确率(Precision@10)从62%提升到78%。
3. 关键模块实现
3.1 智能爬虫系统
爬取携程美食网需要处理几个特殊问题:
- 动态加载:采用Selenium模拟点击"查看更多"按钮
- 验证码:接入第三方打码平台(预算有限时可降级为人工识别)
- 数据去重:采用MD5指纹比对(菜品名+店铺地址+人均价格)
核心爬取逻辑:
python复制def crawl_restaurant(city_id, max_page=10):
session = requests.Session()
proxies = get_proxy() # 从代理池获取IP
for page in range(1, max_page+1):
url = f"https://you.ctrip.com/fooditem/{city_id}/0/p{page}.html"
try:
resp = session.get(url, proxies=proxies, timeout=10)
soup = BeautifulSoup(resp.text, 'html.parser')
# 解析店铺数据
for item in soup.select('.list_item'):
name = item.select_one('.title').text.strip()
address = item.select('.desc span')[1].text
price = item.select('.price')[0].text[1:]
# 持久化存储
Restaurant.objects.update_or_create(
name=name,
defaults={'address':address, 'avg_price':price}
)
except Exception as e:
logger.error(f"第{page}页抓取失败: {str(e)}")
continue
注意:实际项目中需要设置合理的爬取间隔(建议≥3秒),并在headers中添加Referer字段模拟正常访问。
3.2 可视化看板
Echarts配置中最复杂的部分是热力图与散点图的联动:
javascript复制// 初始化地图实例
var myChart = echarts.init(document.getElementById('map'));
var option = {
tooltip: {
formatter: function(params) {
return `${params.name}<br/>
均价: ${params.data.avg_price}元<br/>
评分: ${params.data.rating}星`;
}
},
visualMap: {
type: 'piecewise',
pieces: [
{min: 4.5, color: '#c12e34'},
{min: 4.0, max: 4.5, color: '#e6b600'},
{min: 3.0, max: 4.0, color: '#0092ff'},
{max: 3.0, color: '#999'}
]
},
series: [{
type: 'scatter',
coordinateSystem: 'bmap',
data: convertToMapData(apiData),
symbolSize: function(val) {
return Math.sqrt(val.review_count) * 2;
}
}]
};
这段代码实现了:
- 动态气泡大小:根据评论数调整显示尺寸
- 分段着色:不同评分区间使用不同颜色
- 自定义提示框:展示关键指标
4. 部署与优化
4.1 性能调优
在高并发场景下(实测≥500QPS),我们遇到几个典型问题:
-
推荐延迟高
- 解决方案:预计算用户相似度矩阵,每小时离线更新
- 效果:响应时间从1200ms降至200ms
-
MySQL连接池耗尽
- 配置参数:
python复制DATABASES = { 'OPTIONS': { 'pool_size': 20, 'max_overflow': 100, 'timeout': 30 } } - 配合Django-db-geventpool插件使用
- 配置参数:
-
缓存策略
- 热门推荐:Redis缓存30分钟
- 用户画像:Memcached存储24小时
- 使用装饰器简化缓存逻辑:
python复制@cache_page(60*15) def recommend_view(request): # 视图逻辑
4.2 安全防护
餐饮系统尤其需要注意:
- XSS防御:Django模板自动转义 + 富文本白名单
python复制from django.utils.html import strip_tags clean_content = strip_tags(dirty_content) - CSRF防护:全站启用CSRF中间件
- 数据加密:用户密码使用PBKDF2算法哈希
- 权限控制:基于django-guardian实现行级权限
5. 踩坑实录
5.1 算法冷启动问题
初期新用户推荐效果差,解决方案:
- 混合推荐策略:30%协同过滤 + 70%热门榜单
- 引入用户注册时的口味偏好调查
- 基于LBS的附近商家推荐
5.2 数据不一致案例
某次爬虫异常导致价格单位混乱(美元/人民币混用),修复流程:
- 建立数据质量监控任务
python复制@periodic_task(run_every=crontab(hour=1)) def check_data_quality(): # 检查价格异常值 abnormals = Restaurant.objects.filter( avg_price__gt=1000 ).count() if abnormals > 5: alert_admin() - 增加数据清洗规则
- 建立异常数据回滚机制
5.3 可视化性能优化
初期全国数据渲染卡顿,通过以下措施改善:
- 数据采样:超过5000条时启用等距抽样
- WebWorker异步计算
- 地图分级显示(省级→市级→商圈级)
6. 扩展方向
这个基础架构可以延伸出多个有价值的子项目:
-
智能营销系统
- 基于用户画像的优惠券精准投放
- 流失用户预警模型
-
供应链优化
- 菜品销量预测
- 食材采购建议
-
舆情监控
- 评论情感分析
- 竞争店铺对比
-
小程序扩展
- 扫码点餐集成
- AR菜单展示
在实际运营中,我们后续接入了微信小程序端,使下单转化率提升了40%。关键是在推荐结果页直接嵌入"在线排队"和"优惠买单"功能,形成浏览-决策-消费的闭环体验。