1. 项目概述
湖南旅游景点智能推荐系统是一个基于SpringBoot框架开发的Web应用,旨在为游客提供个性化的旅游景点推荐服务。系统通过爬取湖南地区各大景点的真实数据,结合协同过滤算法分析用户行为(如浏览、收藏、评分等),为用户推荐可能感兴趣的景点。
这个项目是我在完成毕业设计时开发的,前后花了3个月时间,期间踩了不少坑,也积累了一些经验。下面我会详细分享整个系统的设计思路和实现过程。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型
系统采用前后端分离的架构模式,主要技术栈如下:
后端技术:
- 核心框架:SpringBoot 2.7.0
- 数据库:MySQL 8.0
- ORM框架:MyBatis-Plus
- 推荐算法:基于用户的协同过滤算法
- 数据爬取:Jsoup + HttpClient
- 可视化:Matplotlib + Pandas
前端技术:
- 核心框架:Vue.js 3.0
- UI组件库:Element Plus
- 图表库:ECharts
- 构建工具:Webpack
选择这些技术主要基于以下考虑:
- SpringBoot简化了配置,可以快速搭建项目
- Vue.js轻量高效,适合开发交互性强的单页应用
- MyBatis-Plus提供了便捷的CRUD操作
- Jsoup简单易用,适合爬取静态网页数据
2.2 系统架构
系统采用典型的三层架构:
code复制表现层(UI) → 业务逻辑层(BLL) → 数据访问层(DAL)
表现层:负责用户界面展示和交互,使用Vue.js实现响应式前端。
业务逻辑层:处理核心业务逻辑,包括:
- 用户认证与授权
- 景点数据管理
- 推荐算法实现
- 数据统计分析
数据访问层:负责与数据库交互,使用MyBatis-Plus简化数据操作。
3. 核心功能实现
3.1 数据爬取模块
系统需要定期从旅游网站爬取景点数据,包括:
- 景点基本信息(名称、类型、开放时间等)
- 用户评价数据
- 景点热度指标
爬虫实现的关键代码:
java复制public class AttractionCrawler {
private static final String BASE_URL = "https://www.example.com/hunan";
public List<Attraction> crawlAttractions() {
List<Attraction> attractions = new ArrayList<>();
try {
Document doc = Jsoup.connect(BASE_URL).get();
Elements items = doc.select(".attraction-item");
for (Element item : items) {
Attraction attraction = new Attraction();
attraction.setName(item.select(".name").text());
attraction.setType(item.select(".type").text());
// 其他字段解析...
attractions.add(attraction);
}
} catch (IOException e) {
log.error("爬取景点数据失败", e);
}
return attractions;
}
}
爬虫开发经验:
- 设置合理的请求间隔(建议3-5秒),避免被封IP
- 使用User-Agent模拟浏览器访问
- 处理反爬机制,如验证码、动态加载等
- 数据清洗很重要,去除无效和重复数据
3.2 推荐算法实现
系统采用基于用户的协同过滤算法,主要步骤:
- 构建用户-景点评分矩阵
- 计算用户相似度(余弦相似度)
- 找出K个最相似用户
- 基于相似用户的评分预测目标用户对未评分景点的兴趣
算法核心代码:
java复制public class CollaborativeFiltering {
public List<Attraction> recommend(User user, int k) {
// 1. 获取所有用户评分数据
Map<User, Map<Attraction, Double>> userRatings = getRatingsFromDB();
// 2. 计算用户相似度
Map<User, Double> similarities = new HashMap<>();
for (User other : userRatings.keySet()) {
if (!other.equals(user)) {
double sim = cosineSimilarity(user, other, userRatings);
similarities.put(other, sim);
}
}
// 3. 获取Top K相似用户
List<User> neighbors = similarities.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(k)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
// 4. 预测评分并推荐
return predictAttractions(user, neighbors, userRatings);
}
private double cosineSimilarity(User u1, User u2,
Map<User, Map<Attraction, Double>> ratings) {
// 实现余弦相似度计算
}
}
3.3 数据可视化
系统使用ECharts实现多种图表展示:
- 热门/冷门景点对比柱状图
- 景点评分趋势折线图
- 用户行为统计饼图
前端图表配置示例:
javascript复制// 热门景点图表配置
const hotAttractionOption = {
title: {
text: '热门景点TOP10'
},
tooltip: {},
xAxis: {
data: ['张家界', '岳阳楼', '凤凰古城', '衡山', '韶山']
},
yAxis: {},
series: [{
name: '热度',
type: 'bar',
data: [8921, 7643, 6532, 5210, 4876]
}]
};
4. 数据库设计
4.1 主要表结构
系统数据库包含20多张表,核心表如下:
景点信息表(attractions_information)
sql复制CREATE TABLE `attractions_information` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL COMMENT '景点名称',
`type` varchar(32) COMMENT '景点类型',
`open_time` varchar(64) COMMENT '开放时间',
`ticket_price` decimal(10,2) COMMENT '门票价格',
`popularity` double COMMENT '景点热度',
`description` text COMMENT '景点介绍',
`image_url` varchar(255) COMMENT '图片URL',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
用户评分表(user_rating)
sql复制CREATE TABLE `user_rating` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`attraction_id` int NOT NULL,
`rating` double NOT NULL COMMENT '评分1-5',
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_attraction` (`user_id`, `attraction_id`),
KEY `idx_attraction` (`attraction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 索引优化
为提高查询性能,针对常用查询场景添加了索引:
- 景点名称查询:
idx_name - 用户-景点评分查询:
uk_user_attraction - 景点热度排序:
idx_popularity
5. 系统部署
5.1 环境要求
- JDK 1.8+
- MySQL 8.0+
- Node.js 14+
- Redis 5.0+(缓存)
5.2 部署步骤
- 数据库初始化:
bash复制mysql -u root -p < schema.sql
- 后端服务启动:
bash复制mvn spring-boot:run
- 前端构建与启动:
bash复制npm install
npm run build
npm run serve
6. 开发经验与问题解决
6.1 遇到的典型问题
问题1:推荐算法性能瓶颈
当用户和景点数量增加时,协同过滤算法的计算复杂度呈指数增长,导致响应变慢。
解决方案:
- 引入缓存(Redis)存储用户相似度矩阵
- 使用批处理离线计算推荐结果
- 限制相似用户数量(K值)
问题2:爬虫被网站封禁
频繁请求目标网站导致IP被封。
解决方案:
- 使用代理IP池
- 设置随机请求间隔
- 模拟浏览器头部信息
6.2 性能优化建议
-
数据库层面:
- 合理设计索引
- 使用连接池(HikariCP)
- 读写分离(主从复制)
-
应用层面:
- 启用Spring缓存
- 异步处理耗时操作(如推荐计算)
- 前端懒加载和分页
-
算法层面:
- 考虑使用更高效的推荐算法(如矩阵分解)
- 引入实时推荐机制
7. 系统功能展示
7.1 用户界面
首页:展示推荐景点、热门景点和最新资讯

景点详情页:显示景点完整信息和支持用户互动

7.2 管理后台
数据统计面板:可视化展示系统关键指标

景点管理:支持增删改查和批量导入

8. 项目总结
这个项目完整实现了一个旅游推荐系统的核心功能,主要收获包括:
- 掌握了SpringBoot全栈开发流程
- 深入理解了推荐算法原理和实现
- 积累了Web爬虫开发经验
- 学会了性能分析和优化技巧
未来可能的改进方向:
- 引入更多推荐算法(内容基于、混合推荐)
- 增加社交功能(用户关注、分享)
- 开发移动端应用
- 实现实时推荐
整个项目源码已上传到GitHub,有需要的同学可以参考。在开发过程中,最重要的是保持耐心,遇到问题多查阅文档和社区讨论,逐步调试解决。
