这个基于Python的旅游景点信息采集分析可视化系统,是我在指导学生完成毕业设计时开发的一个实战项目。作为一个从事数据分析和Web开发多年的技术人,我发现很多旅游类网站虽然提供了大量景点信息,但缺乏系统性的数据整合和分析功能。这个项目正是为了解决这个问题而生。
系统采用Django作为后端框架,MySQL存储数据,通过selenium自动化采集携程网的景区信息。前端使用HTML结合ECharts等可视化库,实现了从数据采集、存储到分析展示的全流程功能。特别适合计算机相关专业的学生作为毕业设计选题,也适用于旅游行业从业者进行市场分析。
提示:项目完整代码已开源,文末会提供获取方式。建议先收藏,方便后续参考。
选择Python+Django的组合主要基于以下考虑:
数据库选用MySQL而非SQLite,主要因为:
python复制# 示例:Django模型定义
from django.db import models
class Data(models.Model):
name = models.CharField(max_length=100) # 景区名称
level = models.CharField(max_length=20) # 景区等级
score = models.CharField(max_length=10) # 评分
hot = models.CharField(max_length=10) # 热度
comment_count = models.CharField(max_length=20) # 评论数
address = models.TextField() # 地址
detail = models.TextField() # 详情
爬虫部分是本项目的关键难点之一。我们选择selenium而非requests+BeautifulSoup,主要因为:
核心爬取流程:
python复制from selenium import webdriver
from selenium.webdriver.common.by import By
def get_scenic_info(url):
driver = webdriver.Chrome()
driver.get(url)
# 等待页面加载
time.sleep(2)
# 提取景区名称
name = driver.find_element(By.CSS_SELECTOR, '.title').text
# 提取评分
score = driver.find_element(By.CSS_SELECTOR, '.score').text
# 其他数据提取...
driver.quit()
return {
'name': name,
'score': score,
# 其他字段...
}
原始数据存在以下问题需要处理:
我们采用正则表达式和数值转换进行标准化:
python复制import re
def clean_comment_count(comment_str):
# 提取数字部分
num = re.findall(r'\d+', comment_str)[0]
return int(num)
前端可视化使用ECharts库,主要优势:
核心图表配置示例:
javascript复制// 景区等级分布环形图
option = {
title: {
text: '景区等级分布',
left: 'center'
},
tooltip: {
trigger: 'item'
},
series: [
{
name: '等级分布',
type: 'pie',
radius: ['40%', '70%'],
data: [
{value: 1048, name: '5A'},
{value: 735, name: '4A'},
// 其他数据...
]
}
]
};
数据可视化大屏采用响应式布局,主要包含:
使用CSS Grid实现灵活布局:
css复制.dashboard {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-gap: 20px;
padding: 20px;
}
.map-container {
grid-column: 1;
grid-row: 1 / span 2;
}
默认的Django Admin功能有限,我们进行了以下增强:
python复制from django.contrib import admin
class DataAdmin(admin.ModelAdmin):
list_display = ('name', 'level', 'score', 'hot')
search_fields = ('name', 'address')
list_filter = ('level',)
actions = ['export_as_csv']
def export_as_csv(self, request, queryset):
# 导出逻辑...
pass
系统实现基于角色的访问控制:
使用Django内置的权限系统:
python复制from django.contrib.auth.decorators import permission_required
@permission_required('data.change_data')
def edit_data(request, data_id):
# 编辑逻辑...
pass
推荐部署方案:
关键Nginx配置:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
}
location /static/ {
alias /path/to/static/files/;
}
}
python复制# 添加数据库索引
class Data(models.Model):
# 字段定义...
class Meta:
indexes = [
models.Index(fields=['name']),
models.Index(fields=['level']),
]
问题1:页面元素加载不全
python复制from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".title"))
)
问题2:IP被封禁
问题:大数据量下图表渲染慢
javascript复制series: [{
type: 'scatter',
large: true,
largeThreshold: 2000,
// 其他配置...
}]
这个基础系统还可以进一步扩展:
例如实现简单的推荐功能:
python复制from sklearn.neighbors import NearestNeighbors
def recommend_scenic(user_preferences):
# 加载所有景区特征
features = load_all_features()
# 训练KNN模型
model = NearestNeighbors(n_neighbors=5)
model.fit(features)
# 为用户推荐
distances, indices = model.kneighbors([user_preferences])
return indices[0]
在实际开发过程中,我总结了以下几点经验:
一个典型的性能优化示例:
python复制# 不好的写法:N+1查询
for scenic in scenic_list:
print(scenic.comment_set.count())
# 好的写法:使用annotate
from django.db.models import Count
scenic_list = Scenic.objects.annotate(comment_count=Count('comment'))
for scenic in scenic_list:
print(scenic.comment_count)
这个项目的完整源码已经整理好,包含:
获取方式:
建议在本地运行前:
bash复制# 初始化项目
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py runserver
这个项目从构思到实现大约用了2周时间,最难的部分其实是数据采集的稳定性和可视化效果的调优。希望这个分享对正在做类似项目的同学有所帮助。如果在实现过程中遇到任何问题,欢迎交流讨论。