☰
ThinkPHP+Vue构建美食推荐系统:爬虫与智能算法实践
2026/11/4 2:55:19 网站建设 项目流程

1. 项目概述:当美食遇上技术

最近在折腾一个挺有意思的项目——用ThinkPHP+Vue搭建的豆果美食推荐系统。这个系统不仅能爬取豆果网上的海量菜谱数据,还能通过可视化界面把这些美食信息直观地呈现给用户。作为一个经常在厨房翻车的程序员,这个项目完美结合了我的两个爱好:写代码和吃美食。

这个系统主要由三部分组成:后端用ThinkPHP处理数据和逻辑,前端用Vue构建用户界面,中间通过爬虫技术从豆果网获取原始菜谱数据。最让我兴奋的是可视化部分,它能根据用户的浏览记录和偏好,智能推荐可能感兴趣的美食菜谱。想象一下,系统能记住你上次做了宫保鸡丁,这次就给你推荐鱼香肉丝,是不是很贴心?

2. 技术栈选型解析

2.1 为什么选择ThinkPHP+Vue

ThinkPHP作为国内流行的PHP框架,以其简单易用、文档丰富著称。对于美食推荐系统这种需要快速开发的中小型项目特别合适。它内置的ORM和缓存机制,能很好地处理菜谱数据的增删改查。

Vue则是前端开发的利器,它的响应式特性和组件化开发模式,非常适合构建交互复杂的美食推荐界面。通过Vue的数据绑定,我们可以实时更新推荐结果,用户调整筛选条件时,页面无需刷新就能看到新的菜谱推荐。

2.2 爬虫技术选型

考虑到豆果网的页面结构,我们选择了PHP的Goutte库作为爬虫工具。相比Python的Scrapy,Goutte虽然功能稍弱,但胜在与ThinkPHP无缝集成。它基于Symfony的BrowserKit和DomCrawler组件,能轻松处理HTML页面的解析和表单提交。

对于反爬措施,我们主要做了以下几点:

  • 随机User-Agent轮换
  • 请求间隔控制在3-5秒
  • 使用代理IP池(注意遵守robots.txt规则)
  • 模拟真实用户浏览行为

3. 系统架构设计

3.1 数据流设计

整个系统的数据流动是这样的:

  1. 爬虫定期从豆果网抓取最新菜谱数据
  2. 数据经过清洗后存入MySQL数据库
  3. ThinkPHP后端提供RESTful API
  4. Vue前端调用API获取数据并渲染界面
  5. 用户交互数据通过API回传,用于优化推荐算法

3.2 数据库设计

核心表结构包括:

  • 菜谱表(recipes):存储菜谱基本信息
  • 食材表(ingredients):所有食材的字典表
  • 用户表(users):注册用户信息
  • 用户行为表(user_actions):记录浏览、收藏等行为

特别设计了食材-菜谱的多对多关系表,这是实现"根据现有食材推荐菜谱"功能的关键。

4. 爬虫实现细节

4.1 页面解析策略

豆果网的菜谱页面结构相对规整,我们主要通过CSS选择器定位关键信息:

// 示例:提取菜谱标题 $crawler->filter('.recipe-title')->text(); // 提取食材列表 $ingredients = $crawler->filter('.ings li')->each(function ($node) { return $node->text(); });

4.2 反反爬技巧

在实际爬取过程中,我们遇到了几个坑:

  1. 验证码问题:当请求频率过高时会出现
    • 解决方案:降低请求频率,必要时使用OCR识别简单验证码
  2. 动态加载内容:部分数据通过AJAX加载
    • 解决方案:分析XHR请求,直接调用API接口
  3. IP限制:连续请求可能导致IP被封
    • 解决方案:使用代理IP,建议选择按量付费的云服务

重要提示:爬取数据前务必检查robots.txt,控制爬取速度,避免对目标网站造成负担

5. 推荐算法实现

5.1 基于内容的推荐

这是系统的核心算法,主要考虑以下因素:

  1. 菜谱的食材匹配度
  2. 菜谱的烹饪难度与用户水平的匹配
  3. 菜谱的热度(浏览量、收藏量)
  4. 菜谱的发布时间(优先推荐新鲜的)

算法公式可以简化为: 推荐分数 = 食材匹配权重×0.5 + 难度匹配权重×0.2 + 热度权重×0.2 + 新鲜度权重×0.1

5.2 协同过滤的实现

对于登录用户,我们还实现了简单的协同过滤:

  1. 找到与该用户口味相似的其他用户
  2. 推荐这些相似用户喜欢但该用户未浏览过的菜谱

由于冷启动问题,新用户的推荐主要依赖基于内容的方法,随着用户行为数据的积累,协同过滤的效果会逐渐提升。

6. 可视化前端实现

6.1 主要界面设计

系统前端包含以下几个核心页面:

  1. 首页推荐:根据用户偏好展示个性化菜谱
  2. 菜谱详情:完整的制作步骤、食材清单和技巧
  3. 食材搜索:根据现有食材反向查找可做的菜
  4. 个人中心:收藏的菜谱和浏览历史

6.2 关键Vue组件

  1. RecipeCard组件:展示菜谱的卡片,包含图片、标题、难度等
  2. IngredientFilter:食材筛选器,支持多选和搜索
  3. StepByStep:分步展示烹饪步骤,支持图文混排
  4. RecommendationSlider:推荐菜谱的轮播组件

7. 项目部署与优化

7.1 性能优化技巧

在实际运行中,我们发现了几处性能瓶颈及解决方案:

  1. 数据库查询慢:为常用查询添加索引,特别是食材关联查询
  2. 图片加载慢:使用CDN加速,实现懒加载
  3. 推荐计算耗时:预计算热门推荐,实时只计算个性化部分
  4. 爬虫效率低:采用分布式队列,多个爬虫实例并行工作

7.2 安全注意事项

  1. 用户输入过滤:特别是搜索和评论功能,防止XSS攻击
  2. API接口鉴权:使用JWT进行身份验证
  3. 数据库防护:预处理所有SQL语句,防止注入
  4. 爬虫合规性:控制请求频率,尊重robots.txt

8. 实际应用中的问题与解决

8.1 数据不一致问题

初期我们遇到了菜谱数据重复的问题,原因是:

  • 同一菜谱可能有多个URL
  • 菜谱更新后URL可能不变但内容变化

解决方案:

  1. 通过菜谱名称+主要食材生成唯一hash
  2. 建立版本控制,保留历史记录
  3. 定期检查数据一致性

8.2 推荐质量优化

最初的推荐算法存在以下问题:

  1. 热门菜谱总是排在前面
  2. 用户看到太多重复类型的菜谱
  3. 新上传的优质菜谱难以获得曝光

改进措施:

  1. 引入随机因子,增加推荐多样性
  2. 实现"探索与利用"平衡机制
  3. 为新菜谱设置初始权重加成

9. 项目扩展方向

这个系统还有很大的扩展空间,以下是我规划的几个方向:

  1. 移动端适配:开发微信小程序或原生APP
  2. 智能购物清单:根据选择的菜谱自动生成购物清单
  3. 厨友社交:用户间可以关注、分享菜谱
  4. 视频教程:整合烹饪过程视频
  5. 智能厨具对接:与智能烤箱、电饭煲等设备联动

在实际开发中,我发现最耗时的部分不是代码编写,而是数据的清洗和标准化。比如不同菜谱对"适量"、"少许"这类模糊描述的处理,还有食材的别名问题(比如西红柿和番茄)。这让我意识到,在数据驱动的项目中,数据质量往往比算法本身更重要。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询