1. 项目概述
这个基于Python Django与Selenium的旅游景点可视化分析系统,本质上是一个面向智慧文旅领域的大数据决策支持平台。我在实际开发中发现,这类系统最核心的价值在于将分散的旅游数据转化为直观的可视化图表,帮助景区管理者、旅游规划部门和OTA平台做出更精准的运营决策。
系统采用Django作为后端框架,主要处理数据存储、业务逻辑和API接口;前端通过ECharts等可视化库实现"大数据驾驶舱"式的交互界面;而Selenium则用于自动化采集各大旅游平台的景点评价、门票价格等实时数据。特别值得一提的是,我们还尝试引入大模型技术对非结构化文本(如游客评论)进行情感分析和主题提取,这比传统的关键词统计能挖掘出更深层的游客需求。
2. 技术架构解析
2.1 Django后端设计要点
项目采用Django Rest Framework构建RESTful API,模型层主要包含:
python复制class ScenicSpot(models.Model):
name = models.CharField(max_length=100) # 景点名称
location = models.PointField() # 使用GeoDjango存储坐标
popularity = models.IntegerField() # 热度指数
sentiment_score = models.FloatField() # 情感分析得分
class TouristReview(models.Model):
content = models.TextField()
rating = models.FloatField()
spot = models.ForeignKey(ScenicSpot, on_delete=models.CASCADE)
keywords = models.JSONField() # 存储大模型提取的关键词
注意:使用GeoDjango时需要额外安装postgis扩展,在Docker部署时建议使用
postgis/postgis镜像而非标准PostgreSQL
2.2 数据采集方案对比
我们测试了三种数据采集方式:
- 公开API(如高德地图API):响应快但数据维度有限
- Selenium自动化:可获取完整页面数据但容易被反爬
- 第三方数据服务:成本高但数据质量稳定
最终采用混合方案:
python复制from selenium.webdriver import ChromeOptions
options = ChromeOptions()
options.add_argument("--headless") # 无头模式
options.add_argument("--disable-blink-features=AutomationControlled")
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
}) # 隐藏自动化特征
2.3 可视化大屏实现技巧
驾驶舱界面使用Vue.js+ECharts实现,关键配置项包括:
- 热力图使用高德地图API的
Loca组件 - 游客流量趋势图开启
dataZoom滑动条 - 评价词云通过
echarts-wordcloud插件生成
javascript复制// 典型的热力图配置
option = {
tooltip: {
formatter: params => {
return `景点:${params.data[4]}<br/>热度:${params.data[2]}`
}
},
visualMap: {
min: 0,
max: 100,
inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }
}
}
3. 核心功能实现
3.1 实时数据更新机制
系统通过Celery定时任务实现数据自动化更新:
python复制@app.task
def update_scenic_data():
# 1. Selenium采集最新数据
spots = crawl_tripadvisor()
# 2. 调用大模型API分析文本
for spot in spots:
spot['keywords'] = llm_analyze(spot['reviews'])
# 3. 更新数据库
bulk_update(spots)
踩坑记录:初期直接使用ORM的update导致性能瓶颈,后来改用
bulk_update配合django-pgbulk插件,更新10万条数据从120秒降至3秒
3.2 大模型集成方案
针对旅游评论分析,我们对比了三种方案:
- 直接调用GPT-4 API(效果最好但成本高)
- 微调开源模型如ChatGLM3(需要标注数据)
- 使用Prompt优化技巧提升小模型效果
最终采用方案3的优化prompt示例:
code复制你是一个旅游行业专家,请从以下评论中提取:
1. 游客提到的3个核心关键词
2. 情感倾向(1-5分)
3. 改进建议
评论内容:{{review_text}}
3.3 智能推荐算法
基于游客行为数据实现个性化推荐:
python复制def recommend_spots(user):
# 协同过滤
cf_spots = collaborative_filtering(user.id)
# 基于位置的推荐
nearby = ScenicSpot.objects.filter(
location__distance_lte=(user.last_location, 5000)
)
# 融合推荐结果
return hybrid_sort(cf_spots, nearby)
4. 部署与性能优化
4.1 高并发解决方案
通过压力测试发现两个性能瓶颈:
- 景点详情页SQL查询N+1问题
- 热力图数据接口响应慢
优化措施:
- 使用
select_related和prefetch_related - 对地理空间查询添加GIST索引
- 热点数据用Redis缓存
sql复制CREATE INDEX idx_spot_location ON scenic_spot USING GIST(location);
4.2 监控体系搭建
使用Prometheus+Grafana监控关键指标:
- 数据采集成功率
- API响应时间P99
- 大模型调用耗时
告警规则示例:
yaml复制- alert: HighErrorRate
expr: rate(django_http_requests_total{status=~"5.."}[5m]) > 0.1
for: 10m
5. 典型问题排查
5.1 Selenium被检测问题
现象:数据采集时频繁出现验证码
解决方案:
- 随机化操作间隔时间
- 使用
undetected-chromedriver - 配置代理IP池
python复制import random
from time import sleep
def human_like_click(element):
sleep(random.uniform(0.5, 1.2))
element.click()
5.2 地图坐标偏移问题
不同数据源使用的坐标系可能不同:
- 高德地图:GCJ-02
- 百度地图:BD-09
- 原始GPS:WGS-84
需要统一转换:
python复制from coord_convert import transform
def standardize_coord(lng, lat, source):
if source == 'baidu':
return transform.bd09_to_gcj02(lng, lat)
elif source == 'gps':
return transform.wgs84_to_gcj02(lng, lat)
else:
return lng, lat
6. 项目扩展方向
在实际运营中,我们发现可以进一步扩展:
- 接入实时人流监控(通过手机信令数据)
- 增加旅游路线规划算法
- 开发微信小程序端入口
特别是路线规划算法,结合了Dijkstra算法和游客偏好:
python复制def plan_route(start, spots, max_time):
graph = build_attraction_graph(spots)
return dijkstra(graph, start, weight_fn=lambda x: x['time'] * x['crowd'])