资讯动态

Django构建旅游推荐系统:数据采集与混合推荐实战

发布时间:2026/9/18 6:20:49 来源:尧图企业网站定制
1. 项目概述去年接手了一个旅游行业的数据分析项目客户希望建立一个能够整合多源数据并提供个性化推荐的系统。经过三个月的开发迭代我们基于Django框架构建了一套完整的旅游数据分析与推荐平台。这个系统不仅能够处理日均百万级的旅游数据还能为不同用户生成千人千面的推荐结果。在实际开发中我们遇到了几个关键挑战如何高效采集分散在各平台的旅游数据如何处理非结构化的用户评论数据如何设计推荐算法平衡准确性和实时性本文将分享我们在解决这些问题过程中积累的实战经验。2. 系统架构设计2.1 整体技术栈选型选择Django作为后端框架主要基于以下考虑ORM系统完善能快速构建数据模型自带Admin后台方便数据管理丰富的第三方库支持如DRF用于API开发成熟的社区和文档支持数据库选用MySQL 5.7主要因为事务支持完善对JSON字段的良好支持存储半结构化数据与Django的深度集成2.2 分层架构详解系统采用典型的三层架构数据采集层使用Scrapy框架构建分布式爬虫集群针对不同数据源定制采集策略如景点基础信息、用户评论、价格数据实现增量采集机制通过时间戳和MD5校验去重数据处理层数据清洗流水线处理缺失值、异常值、重复数据中文文本处理Jieba分词、SnowNLP情感分析特征工程构建用户画像、景点特征矩阵业务应用层推荐引擎混合推荐算法数据可视化服务Echarts动态图表用户行为分析埋点数据统计3. 核心模块实现3.1 数据采集模块我们开发了多线程异步采集系统关键代码如下class TourismSpider(scrapy.Spider): name tourism custom_settings { CONCURRENT_REQUESTS: 16, DOWNLOAD_DELAY: 0.5, RETRY_TIMES: 3 } def parse(self, response): # 解析景点基础信息 item TourismItem() item[name] response.css(h1.spot-name::text).get() item[location] response.css(div.address::text).get() item[rating] float(response.css(span.score::text).get()) # 处理用户评论分页 yield from self.parse_reviews(response) yield item def parse_reviews(self, response): # 解析评论数据 for review in response.css(div.review-item): yield { user_id: review.css(::attr(data-userid)).get(), content: review.css(p.content::text).get(), rating: int(review.css(span.star::attr(class)).re_first(rstar-(\d))), date: review.css(span.date::text).get() } # 自动翻页处理 next_page response.css(a.next-page::attr(href)).get() if next_page: yield response.follow(next_page, self.parse_reviews)注意事项需要合理设置请求间隔避免被封禁重要数据字段需要做空值校验分布式部署时需要共享去重队列3.2 推荐算法实现采用混合推荐策略协同过滤内容推荐class HybridRecommender: def __init__(self): self.cf_model CollaborativeFiltering() self.cb_model ContentBased() self.user_features load_user_features() self.item_features load_item_features() def recommend(self, user_id, top_n10): # 获取用户历史行为 user_history get_user_history(user_id) # 协同过滤推荐 cf_recs self.cf_model.recommend(user_id, top_n*2) # 内容推荐 cb_recs self.cb_model.recommend( user_featuresself.user_features[user_id], item_featuresself.item_features, exclude_ids[x[item_id] for x in user_history], top_ntop_n*2 ) # 混合排序 hybrid_recs self._blend_recommendations(cf_recs, cb_recs) return hybrid_recs[:top_n] def _blend_recommendations(self, cf_recs, cb_recs): # 加权融合算法 blended {} for rec in cf_recs: blended[rec[item_id]] rec[score] * 0.6 for rec in cb_recs: if rec[item_id] in blended: blended[rec[item_id]] rec[score] * 0.4 else: blended[rec[item_id]] rec[score] * 0.4 return sorted(blended.items(), keylambda x: x[1], reverseTrue)算法调优经验协同过滤在用户行为数据充足时效果更好内容推荐能解决冷启动问题实际应用中需要动态调整混合权重4. 性能优化实践4.1 数据库优化针对旅游数据特点做了以下优化索引策略为高频查询字段创建组合索引使用覆盖索引减少回表操作CREATE INDEX idx_spot_location ON tourism_spot(location, rating);查询优化使用select_related/prefetch_related减少查询次数对大文本字段使用延迟加载spots TourismSpot.objects.filter( location__contains北京 ).select_related(category).only(name, image_url, rating)分区表设计按地区分片存储景点数据按时间分区存储用户行为数据4.2 缓存策略采用多级缓存架构热点数据使用Redis缓存景点基础信息TTL 1小时推荐结果TTL 30分钟使用Django缓存框架缓存模板片段CDN加速静态资源访问缓存更新策略def update_spot_cache(spot_id): spot get_object_or_404(TourismSpot, pkspot_id) cache_key fspot_{spot_id}_v{spot.version} redis_client.setex( cache_key, timedelta(hours1), json.dumps(spot.to_dict()) ) # 异步更新推荐结果 update_recommendations.delay(spot_id)5. 部署与监控5.1 生产环境部署使用Docker-compose编排服务version: 3.8 services: web: build: . command: gunicorn core.wsgi:application --bind 0.0.0.0:8000 volumes: - .:/code ports: - 8000:8000 depends_on: - redis - db db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_DATABASE: tourism volumes: - db_data:/var/lib/mysql redis: image: redis:6 ports: - 6379:6379 celery: build: . command: celery -A core worker -l info volumes: - .:/code depends_on: - redis - db volumes: db_data:5.2 监控方案应用性能监控使用Prometheus收集指标Grafana展示关键指标关键指标API响应时间推荐服务延迟数据库查询性能日志管理ELK收集分析日志关键日志类型数据采集异常推荐算法执行日志用户行为日志告警机制设置阈值告警如错误率1%关键业务指标监控如推荐点击率下降6. 典型问题与解决方案6.1 数据不一致问题现象不同来源的景点信息存在冲突解决方案建立数据置信度评估体系实现基于规则的冲突解决机制人工审核关键数据字段def resolve_conflict(values): # 优先级官方数据 高评分来源 最新数据 official [v for v in values if v[source] official] if official: return official[0] high_rating [v for v in values if v[rating] 4] if high_rating: return max(high_rating, keylambda x: x[rating]) return max(values, keylambda x: x[update_time])6.2 冷启动问题现象新用户/新景点缺乏行为数据解决方案基于内容的推荐作为兜底利用地域特征进行初始推荐引导用户进行偏好选择def cold_start_recommend(user_ipNone, user_regionNone): if user_region: spots TourismSpot.objects.filter( location__containsuser_region ).order_by(-rating)[:20] else: spots TourismSpot.objects.order_by(-popularity)[:20] return calculate_diversity(spots)7. 项目演进方向在实际运营过程中我们发现以下几个优化方向值得关注实时推荐当前系统采用T1的批处理模式下一步计划引入Flink实现实时推荐多模态数据处理增加对景点图片、视频数据的分析能力可解释性推荐向用户解释推荐理由提升信任度A/B测试框架建立完善的算法评估体系这个项目给我的深刻体会是旅游推荐系统不仅需要强大的技术支持更需要深入理解用户的实际需求。我们在迭代过程中发现简单的算法指标提升并不总能带来用户体验的改善有时候一个合理的数据展示方式或者流畅的操作流程反而更能获得用户认可。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价