资讯动态

基于Python的内蒙古旅游景点数据分析系统搭建详解

发布时间:2026/10/19 3:52:46 来源:尧图企业网站定制
要说做数据分析系统很多教程一上来就贴代码讲得云里雾里。这次我打算换个思路从“为什么这么做”开始把我搭建一个基于Python的内蒙古旅游景点数据分析系统的完整过程拆开揉碎讲清楚。这套系统可以帮你快速掌握景区热度、游客评价、价格分布、地域特征和季节性规律无论是用于毕业设计、个人作品集还是正经的分析报告都有直接的参考价值。1. 设计目标与整体架构先想清楚要做成什么很多人拿到“数据分析系统”这种题目就急着写爬虫、调可视化库结果做到一半发现数据维度对不上业务问题图表堆了一堆却说不出所以然。我在动手之前先花了一整天梳理需求把整个系统拆成了几个明确的层次。1.1 需求拆解内蒙古旅游景点这个题目特殊在哪内蒙古的旅游资源有个很典型的特点地域跨度极大从东边的呼伦贝尔草原到西边的阿拉善沙漠景点类型高度分化并且基本按盟市聚集。这就导致做分析时不能只看一个全局均分必须带着地域维度、类型维度去看数据。通常的数据分析系统无非是这几个模块数据采集、数据清洗、数据存储、数据分析、可视化展示。但放到“内蒙古旅游景点”这个具体场景里有些需求会变得特别突出热度评估不能只看评分评分天然带有幸存者偏差还得看评论量级、推荐率这类支撑性指标。景点类型需要归一化处理比如“草原”“草原旅游区”“草原度假村”本质上是同一类不合并的话后续分析会稀碎。门票价格存在区间值、免票、季节性价格差异肚子里的数据没法直接进模型。可视化上必须输出“盟市维度”“类型维度”“时间维度”的对比单纯一个全国散点图对这个题目毫无意义。我最终把系统定义为一个从公开旅游平台采集内蒙古主要景点数据经过清洗入库然后按地域、类型、热度、价格、游客反馈等维度做标准化分析最后通过Web页面可视化输出的完整流程系统。1.2 技术选型为什么是Python全家桶而不是其他方案做过类似项目的人应该都懂数据分析这块用Python基本是标配。但不是每个工具都得用上才算“全面”选型的关键是每个组件都能解决一个明确问题。具体的技术栈我这样定环节工具选型理由数据采集Python Requests 正则/JSON解析轻量、可控反爬策略可以随用随调比框架更灵活数据清洗Pandas NumPy处理缺失值、类型归一化、区间转换效率极高数据存储SQLite Pandas to_sql轻量零配置单机分析场景完全够用后端服务Flask轻量级Web框架和数据分析代码结合非常自然前端可视化ECharts 原生HTML/JS交互能力强地图、雷达图、热力图各类型都支持部署本地局域网 Waitress毕业设计演示场景不需要复杂的WSGI配置反过来看看哪些地方我不建议用重型工具。Hadoop、Spark这种分布式框架对几万条景点数据来说纯属杀鸡用牛刀引入只会增加部署复杂度毫无收益。MySQL也不用上SQLite单文件即插即用提交代码的时候直接把数据库一起打包别人拿到就能跑这对“交付一个可直接演示的系统”来说比什么都重要。1.3 系统分层与数据流向这个系统我分了四层数据采集层从公开网页爬取原始数据包括景点名称、所在城市/盟市、评分、评论数、门票价格、简介、推荐游玩时长等字段。数据治理层去重、缺失值填补、字段格式化、类型归一化、价格区间解析。分析层基于治理后的数据生成统计指标如盟市景点数量排行、均分排行、评论热度榜、门票价格分布、类型与评分相关性等。展示层Flask提供接口页面通过Ajax拉取JSON数据渲染成图表和表格同时提供基础筛选功能。数据流向就一句话原始HTML → 结构化DataFrame → SQLite → 接口JSON → ECharts图表。每一步之间都保留了独立模块以后想换数据源或者加分析维度不动全局就能扩展。2. 数据采集与清洗把脏数据变成能用的表数据采集是整个系统的地基。这一块如果出了问题后面分析做得再漂亮也是空中楼阁。2.1 爬虫字段设计从业务反推需要哪些字段我在设计爬虫字段之前先把“内蒙古旅游景点数据分析”这个目标拆成具体的分析问题再反推需要的字段要分析盟市热度 → 需要“所在盟市”和“评论数”字段。要分析景点类型的人气差异 → 需要“景点类型”和“评分评论数”字段。要分析消费水平 → 需要“门票价格”和“购票类型”字段。要做季节性建议 → 需要“建议游玩时长”和“最佳游玩季节”字段。最终的字段集为景点名称、所在盟市、景点类型、评分、评论数、门票参考价、购票类型成人票/免费/区间票、简介、建议游玩时长、推荐季节。这个字段集有一个容易被忽略的点评论数。只看评分的分析基本都是错的评分可以刷、可以偏高但评论数一定程度上反映了真实游客规模。我把“热度指数”定义为“评分×log(评论数1)”后面会说为什么。2.2 爬虫实现思路与反爬应对我采用的是纯Requests库请求头模拟浏览器身份加上Cookie和Referer伪装。下面这个代码片段是我用来获取景点列表页并解析JSON数据的核心逻辑def fetch_page_poi_list(page): session create_session() # 构造查询参数这里用到了城市筛选、页码、排序方式 params { cityId: , page: page, limit: 20, sort: 5, # 按热度排序 } headers build_headers() resp session.get(https://example-api.tourplace.com/v1/poi/list, paramsparams, headersheaders, timeout10) if resp.status_code ! 200: raise RuntimeError(f页面请求失败, 状态码: {resp.status_code}) data resp.json() if data.get(ret) ! success: raise RuntimeError(f返回数据异常: {data.get(msg)}) return data.get(items, [])我这里把真实请求地址做了脱敏处理“example-api.tourplace.com”是示意用的。实际开发时你也应该用公共接口数据源但要注意几点不要高并发请求一次只开一个线程间隔控制在1-2秒之间。对毕设来说数据量几千条就够没必要为了快把反爬惹毛。请求头里必须有完整的UA和Accept-Language否则很多接口会拒绝服务。解析JSON时先打印两层结构确认字段名不要靠猜访问嵌套字典。采集过程中最常遇到的问题是编码。内蒙古的景点名称里有大量汉字和生僻地名HTML或接口返回如果声明了charset但实际编码不一致解析出来全是乱码。我的做法是统一用resp.content.decode(utf-8, errorsignore)反正接口返回的JSON本身就是UTF-8直接用content再解码更安全。2.3 数据清洗中的关键细节类型归一化与价格解析原始采集到的数据有几个痛点第一同一个景点在不同页面会有不同写法。比如“成吉思汗陵旅游区”和“成吉思汗陵”在评论数相差巨大的情况下会被当成两条数据。我这边做了两步处理一是按景点名称分组保留评论数总和、取最高评分二是同时按地理坐标去重反正内蒙古的5A级景区就那么多跨城市重复的情况很少按“盟市名称”联合去重已经够用了。第二景点类型非常混乱。同样是草原有时候叫“草原”有时候叫“草原旅游区”还有的叫“草原度假区”或“草原湿地”。我建立了一个简单的映射词典做归一化type_mapping { 草原: 草原, 草原旅游区: 草原, 草原度假村: 草原, 草原湿地: 草原湿地, 湿地: 湿地, 森林公园: 森林, 地质公园: 地质, 沙漠: 沙漠, 沙漠旅游区: 沙漠, 博物馆: 博物馆, 纪念馆: 纪念馆, 寺庙: 宗教文化, 古遗址: 历史遗迹, 度假区: 综合度假, 自然保护区: 自然生态, } def normalize_type(raw_type): if not isinstance(raw_type, str): return 其他 for k, v in type_mapping.items(): if k in raw_type: return v return 其他第三门票价格五花八门。有的景点写“0元”免费有的写“80元”有的写“120元起”还有的写区间“60-100元”。我都按照统一的策略解析成“最低参考价”和“最高参考价”两列区间取的逻辑是区间价取两端单一价格两端取相同值免费就是0。def parse_price(price_raw): if price_raw is None: return [None, None] text str(price_raw) if 免 in text or text.strip() 0: return [0.0, 0.0] nums re.findall(r\d\.?\d*, text) if not nums: return [None, None] if len(nums) 1: v float(nums[0]) return [v, v] else: return [float(nums[0]), float(nums[-1])]这一步做完之后数据表的基本质量才算过关。我常跟人讲一个体会数据清洗占据整个项目60%以上的时间但也是最有价值的部分。很多所谓“分析结果不对”根子都在清洗阶段埋了雷。3. 核心分析指标与业务结论不只是画图表系统能跑之后我开始琢磨这才是数据分析最核心的部分——指标体系怎么建。市面上很多旅游分析系统只做了“统计”没做“分析”区别在于统计回答的是“有多少”分析回答的是“为什么”和“所以呢”。3.1 热度指数修正纯评分偏差我计算热度指数的公式是热度指数 评分 × log(评论数 1)。为什么不用评分直接排序举两个真实例子一个偏远景点有5条评论评分4.9另一个知名景区有2万条评论评分4.6。如果按评分排偏远景点排第一这对游客决策毫无参考意义。评论数取对数则能平滑量级差异把“有口碑”和“游客多”两个因素综合进去排序更有解释力。data_df[热度指数] data_df[评分] * np.log1p(data_df[评论数])实现之后就一行代码但背后的业务思考才是这个项目的真正价值。最终结果按盟市聚合后会出现一个有意思的现象呼和浩特、呼伦贝尔、锡林郭勒稳居第一梯队巴彦淖尔、乌海相对靠后。呼伦贝尔的景点数量不是最多的但热度指数总量最高因为它有呼伦贝尔大草原、额尔古纳湿地等几个真正的流量担当。呼和浩特则是数量多、分布广靠博物馆和历史文化类景点拉起来总量。3.2 地域维度盟市资源分布与热度差异我做了两个角的分析按盟市统计景点数量和平均评分再按盟市统计评论总量和热度指数。景点数量排行方面呼和浩特和锡林郭勒最多这符合资源禀赋——首府城市景点密集且类型多样。平均评分层面阿拉善虽然景点少但AAAAA级别的胡杨林景区评分极高平均分拉到了4.8。巴彦淖尔的景点数量少且评分集中在4.2-4.4说明当地旅游资源开发程度有待提升但同时也意味着发展空间大。这些结论放在报告里是很有说服力的。我特意做了个矩阵图横轴是景点数量纵轴是平均热度指数这样能直观显示“资源多但热度低”和“资源少但热度高”的差异化区域。3.3 类型维度不同类别景点的表现差异对归一化后的景点类型做分组统计我发现几个值得写的点自然生态类和草原类景点数量占比接近40%评论数占比超过50%说明内蒙古的吸引力核心还是大草原和原生态自然风光。历史文化类博物馆、遗迹、寺庙平均评分普遍比自然类高因为能去的游客大多带着明确文化诉求评价往往更正面。沙漠类景点两极分化明显。头部沙漠景区热度极高但大多数沙漠相关景点评分不高且评论少只有专业游客才会去深度游。综合度假类数量少但评论量大说明游客更愿意去“什么都有”的地方一站式度假是趋势。这类分析结论对游客是参考对旅游规划部门就是决策依据。我把它写成一个分组对比表放在系统页面上比单纯柱状图好懂。3.4 价格与热度相关性免费景区的优势在哪我把景区分成免费0元、0-50元、50-100元、100元以上四档和热度指数、评论数做了联立分析。结论很清晰免费景区的评论数总量不低但热度指数未必最高因为免费景区的评分通常偏低——游客期望值低带来的负面评价更容易出现。50-100元档是热度指数最高的区间这个区间集中了一批体验成熟、运营规范的景区。这里我特别做了分组动画图表鼠标悬浮能看到每个档位的具体景点列表这套交互对答辩展示非常加分。4. 系统实现从数据到可视化的展示全链路光有分析结果还不行这个系统最终要给人看我用Flask做了轻量级Web页面把分析结果和图表打包展示出来。4.1 Flask接口设计后端只做一件事根据前端参数返回JSON数据。我设计了几个接口总览统计接口、盟市分布接口、类型分布接口、价格热力接口、景点排行接口和筛选查询接口。核心代码示意如下from flask import Flask, request, jsonify import pandas as pd app Flask(__name__) df pd.read_sql(SELECT * FROM scenery_data, engine) app.route(/api/overview) def api_overview(): total len(df) avg_score round(float(df[评分].mean()), 2) total_comments int(df[评论数].sum()) return jsonify({ 景点总数: total, 平均评分: avg_score, 总评论数: total_comments, 城市数量: df[所在盟市].nunique(), }) app.route(/api/city_rank) def api_city_rank(): result ( df.groupby(所在盟市) .agg({景点名称: count, 评分: mean, 评论数: sum}) .reset_index() ) return jsonify(result.to_dict(orientrecords))因为前端用Ajax异步拉接口后端完全无渲染逻辑部署和调试都省心。还有个好处如果以后想看实时数据只要保证数据库更新就行前端一行不用改。4.2 可视化选图思路图表的选择直接决定分析结论能不能被一眼看懂我的选图逻辑是图表类型用途为什么选它柱状图盟市景点数量排行对比个数的差别最直观折线图价格区间与热度趋势展示连续变量的变化趋势雷达图各盟市多指标对比同时看数量、评分、评论三个维度散点图评分与评论数关系排除异常点和寻找聚类簇地图热力图景点地域分布内蒙古地域辽阔地域特征强烈词云景点简介高频词快速呈现游客关注的话题其中地图热力图的实现我费了一点功夫。ECharts的地图组件需要内蒙古各盟市的GeoJSON文件我使用了一个开源社区的简化版GeoJSON配置好之后把盟市名称和景点数量映射进去效果非常好。4.3 前端页面交互逻辑系统首页分四个区块第一块是总览指标卡片展示景点总数、平均评分、总评论数、盟市数量四个核心数。第二块是两张对比图左侧盟市景点数量柱状图右侧盟市热度排行柱状图。第三块是地图热力图和价格分布折线图左右并列。第四块是底部排行榜列表默认按热度指数降序点击每一行可以展开景点详情。交互上我只保留了一个核心筛选器按盟市筛选。本来还做了类型筛选、价格区间筛选但演示时发现参数一多反而干扰重点。做系统不是功能越多越好核心结论能第一时间呈现才叫好的分析系统。5. 调试与部署中踩过的实用坑这个系统从0到能演示前后调试了大概一周。大多数坑都不是什么高级技术问题但每一个都足以卡住半天分享给需要做类似毕设或项目的人参考。5.1 爬虫调试反爬机制与数据失真我最初用的是静态页面解析结果页面结构调整几次之后解析规则就失效了。后来升级成直接调接口拿JSON稳定性大幅提升。但接口也不是完全开放必须携带特定请求签名才能访问。我采用的办法是在浏览器里打开开发者工具找到实际的请求样例把headers完整复制过来。途中我发现还有个防抓取深坑接口返回的评论数偶发为0可能是做了随机降权测试。如果直接入库会导致热度指数计算错误。我在清洗时统一处理评论数为0的景点热度指数用“评分×0.5”作为兜底并将原因记录在日志里。这样数据分析部分永远不会因为缺失数据报错。5.2 Pandas转JSON精度问题和中文乱码第一次把SQLite数据读出来转JSON给前端时评分变成了浮点数科学计数法格式直接显示成“4.7000000000001”。原因是Pandas的float64在JSON序列化时不做小数位截断解决方式是统一用round之后转原生类型先转成列表再交给jsonify。还有一次前端JS解析接口数据时中文变成了一串反斜杠转义符排查半天发现是Flask的JSON配置在旧版本默认对非ASCII字符做了转义。我用app.config[JSON_AS_ASCII] False关闭掉了转义中文正常显示。5.3 SQLite写入时DataFrame列名带空格采集表里有些字段名是从HTML结构中直接拿的带了空格和特殊字符。to_sql的时候这些列名会被原样写入后续SQL查询就得加反引号非常麻烦。我干脆在清洗阶段统一重命名成规范列名后续所有代码都不用再去迁就字段名了。5.4 ECharts地图联动的血泪经验地图和柱状图联动时ECharts要求地图注册名和series.name完全一致大小写差一个字符都匹配不上。我第一次用的是“呼伦贝尔市”柱状图用的“呼伦贝尔”结果地图一片空白。后来我把所有盟市名称统一去掉了“市”后缀两处保持一致问题解决。这类问题只能说是经验问题遇到一次以后就不会再犯。5.5 部署细节本机演示与局域网访问关闭Debug开发阶段Flask的Debug模式很方便但真正给别人演示时如果有人恶意访问Debug控制台系统等于裸奔。我在部署脚本里强制关闭Debug用Waitress跑生产模式from waitress import serve serve(app, host0.0.0.0, port5000)同时绑定了0.0.0.0这样同一局域网内的其他电脑也能通过IP访问演示页电脑屏幕上展示手机上同步操作演示效果很好。6. 后续可扩展的方向与个人经验总结这个系统做到演示级别已经完成但如果你打算把它继续完善我从实际需求出发给几个方向参考。6.1 增加数据源丰富度目前的数据以公开接口为主后续可以考虑加入景区官方公告、旅游攻略社区的游记文本数据。结合情感分析可以做“游客满意度情绪面”比单纯评分更能透视口碑。具体做法是先把评论文本清洗分词再用情感词表打标最后聚合到盟市级别做情绪对比。6.2 加入时间维度做动态趋势现在看到的是静态截面数据如果持续周期性采集可以按月度做“热度同比环比”分析。比如呼伦贝尔在6-8月热度暴涨这是季节性规律阿拉善则在国庆前后因为胡杨林进入峰值。时间序列模型能预测热度趋势无论对管理者还是游客都有很高实用价值。6.3 突出系统本地化部署能力这个系统所有组件都能装在一台普通笔记本上SQLite数据库方便备份完全不需要联网和云端。依赖可以在代码里做成requirements.txt一次性安装即可。对课程设计、毕业设计和简历项目来说这种轻量可靠的特点反而更受认可。最后分享几个实际体会。第一数据分析系统的成败不在可视化炫不炫而在指标定义是否合理。第二清洗数据的功夫永远是值得的数据质量决定了分析上限。第三做这种综合项目先把数据链路打通再考虑展示效果。如果看到这里的读者有正在做类似“X省旅游景点数据分析系统”的希望这篇内容能帮你少走几天弯路。把每一层的工作拆解清楚按部就班执行一定能交付一个完整可靠可演示的作品。

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

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

免费获取报价 →
↑