做一个说走就走的短途旅行时被酒店价格坑过之后,我就一直想做一件事:把携程网上那些零散的酒店信息、用户评价、价格区间抓下来,用Python做一轮数据可视化分析,看看同一座城市里,价格和口碑到底有没有关系,哪个片区的酒店性价比最高,用户吐槽最多的点又集中在哪。折腾了几个周末,我总算把“基于python的携程网数据可视化分析”这条链路完整跑通了,从爬虫采集、数据清洗到图表输出,每一步都踩了不少坑。今天就把整个项目的设计思路、核心代码和排错过程整理出来,给同样想拿Python练手数据分析,又不想只对着Kaggle那种现成数据集的朋友做份参考。
这个项目本质上不是什么高深算法,它最吸引人的地方在于数据是真实、动态且带噪声的——酒店评分里有“4.5/5分”这种字符串、价格里有“¥488起”这种带单位带文字的文本、评论量有“1.2万条评价”这种需要换算的计数,这些恰恰是日常工作中最常见的数据形态。处理完这些脏数据,再用matplotlib、pyecharts把它们变成直观的图表,这个过程对Python爬虫、Pandas清洗、可视化三块能力的锻炼非常全面。不管你是刚学完Python基础语法,还是已经在写爬虫但没做过完整数据分析项目,这条项目路径都值得走一遍。
1. 为什么选择携程数据:酒店点评背后隐藏的决策密码
先说说这个项目的出发点。很多人学Python数据分析,第一步往往卡在“找不到合适的数据源”。公开数据集虽然干净,但缺少真实项目那种“需要自己想办法”的感觉。而携程网作为国内头部OTA平台,天然具备几个非常适合练手的特点:数据维度丰富、更新频率高、反爬机制适中、页面结构稳定。
1.1 数据源的价值评估:不是所有平台都适合做分析
携程网的数据覆盖了酒店、机票、景点门票、旅游线路、攻略笔记等多个板块,其中酒店板块的数据对初学者尤其友好。以酒店搜索列表页为例,每条酒店记录至少包含酒店名称、区域位置、用户评分、点评数量、最低价格、酒店图片链接等字段。这些字段组合在一起,能回答非常多实际问题:
- 某个城市不同片区的酒店均价差多少?
- 高评分酒店的起步价通常集中在哪个区间?
- 点评量大的酒店是不是真的意味着“值得住”?
- 用户评论里出现频率最高的词是“干净”“服务好”还是“隔音差”“位置偏”?
对比同类型的飞猪、美团,携程的页面结构相对规整,数据接口的返回格式也比较稳定,对新手来说解析难度适中。而且携程的搜索列表页支持按行政区划分,这为后续做“区域维度对比分析”提供了天然的数据分层逻辑。
1.2 分析目标定义:先想清楚要回答什么问题
动手写代码之前,我建议你先拿出一张纸,把分析目标写下来。很多人做数据分析项目容易犯一个毛病:数据抓了一堆,图表画了一大屏,最后却说不清结论是什么。我在这个项目里明确设定了四个核心分析目标:
- 描述性分析:目标城市酒店的总体价格分布、评分分布是怎样的?
- 关系分析:酒店价格与用户评分之间是否存在相关关系?
- 对比分析:不同行政区/商圈的酒店均价和口碑对比如何?
- 文本分析:用户评论中的高频关键词能反映出哪些共性诉求?
这四个目标分别对应了后面的直方图、散点图、横向条形图和词云图。把问题定义清楚,你才知道每张图该画什么、数据该存成什么格式,而不是抓完数据再对着字段发呆。
1.3 数据使用的合规边界:个人学习项目也要有分寸
这里必须多提醒一句:任何爬虫项目都要有边界意识。我这套代码仅用于个人学习和技术验证,采集频率控制在低频范围,不会对目标站点造成访问压力。如果你是做商业项目或公开发布分析报告,请务必查阅目标平台的Robots协议和用户协议,必要时通过官方API获取数据。爬虫技术本身是中性的,但使用场景必须合规。这个分寸感,是每个Python开发者踏入数据采集领域前就该有的职业素养。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据采集层的架构选择:Requests还是Selenium
数据采集是整个项目的源头,这一层如果设计不好,后面清洗和可视化做得再漂亮都是白搭。我在最初版本里犯过一个典型错误:直接用Requests去请求携程的酒店搜索页,结果拿回来的HTML里根本没有酒店列表数据——因为现在很多页面是异步加载的,列表数据是通过XHR接口动态渲染出来的。
2.1 页面加载方式分析:先搞清楚数据是从哪来的
打开携程酒店搜索页,F12进入开发者工具,切到Network面板,刷新页面,你会看到几十个请求。逐个点开看,会发现酒店列表数据实际来自一个包含大量参数的JSON接口,而不是最初的HTML文档。所以正确做法应该是:找到真正的数据接口,分析它的URL参数和返回结构,再用Requests模拟请求。
我以“杭州”为例,搜索接口的URL参数大致包含这些维度:城市ID、入住日期、离店日期、页码、排序方式、筛选条件等。其中城市ID是关键参数,不同的城市对应不同的数字编码。在代码里,我们可以把这些参数整理成一个字典,方便后续切换城市和分析条件。
python复制import requests
def build_search_url(city_id, page=1, sort_type="recommend"):
base_url = "https://you.ctrip.com/api/hotels/search"
params = {
"cityId": city_id,
"page": page,
"sortType": sort_type,
