☰
从开通时间到列车时刻:2003-2025年高铁与航线数据整理实战
2026/10/15 10:36:27 网站建设 项目流程

如果有人让我整理一份2003年到2025年的高铁开通时间、高铁线路信息、高铁列车信息和飞机航线信息数据,我一听就头大。这几年我做过不少交通类数据项目,深知这四类数据表面上看都是一张张表格,实际上完全是四个世界:开通时间是离散的时间事件,线路信息是半静态的属性档案,列车信息是几个月就调一次的动态计划,航线数据更是跟着航季走一年变两轮。第一次做这套数据的时候,我花了一个星期才跑通第一版,后来反复迭代了三次,才敢把数据对外输出。如果你也在做类似的事,这篇就把我踩过的坑、筛过的数据源、最终落地的表结构一次性讲清楚。

1. 先理清楚:四类数据不是同一物种,字段设计决定数据能不能用

拿到这个项目标题,最容易犯的错误是把所有信息塞进一张大宽表里。我自己第一版就吃了这个亏。你要知道,高铁开通时间、高铁线路信息、高铁列车信息、飞机航线信息这四类数据,它们在更新频率、数据粒度和可靠性上完全不一样,硬塞在一起只会让后续查询和维护变成灾难。

1.1 开通时间:这是一次性事件数据,不是区间数据

高铁开通时间本质上是一个“事件”:某条线路在某年某月某日开始正式办理客运业务。它的数据粒度是“线路”,记录重点是日期、线路、首发区间。这里有一个很容易忽略的细节——一条线路往往不是一次性全线开通,而是分段开通。比如某条干线,可能先开通中间某段,几个月后再开通两端剩余段,甚至有些线路在开通后的第二年又延伸了几个站。所以“开通时间表”不应该以整条线路为最小单位,而应该以“开通事件”为最小单位,每行记录一次分段开通行为,包含:线路代号、区间起点、区间终点、开通日期、设计时速、运营时速等字段。

我之前整理2011年之前的早期线路时,就遇到过同一线路有多个“开通日期”的说法:有人说试运营日,有人说正式开通日,有人说全线贯通日。这个问题的根源在于“开通”本身有不同口径。所以我建议在表里增加一个字段叫“事件类型”,区分“开通运营”和“全线贯通”。前者是真正意义上的商业运营开始,后者只是工程建设意义上的打通,两者差几个月非常正常。

1.2 线路信息:半静态档案,但也不是一成不变

高铁线路信息的核心是:线路名称、线路等级(客运专线或客货共线)、里程、设计时速、沿途设站数量。这类数据相对稳定,修改频率低,但它存在两个坑。

第一个坑是里程的口径。同一条线路,正线长度、运营里程、延展长度三个数字经常不一致。正线长度指上下行正线的平均长度,运营里程则可能包含联络线、动走线等辅助线路的折算。我采用的规则是:统一采用“正线长度”,并在字段名上标明口径,后续做线网密度类分析时才不会算出荒谬的数值。

第二个坑是线路等级。不是所有设计时速超过200公里的线路都能叫高铁,这里面有客运专线和客货共线的本质区别。前者基本上只跑动车组列车,后者还会跑普通货车和普速客车,其班次规律、可用时段完全不同。整理列车信息和做可达性分析时,如果把客货共线线路当作纯客专处理,判断某两地之间是否“有高铁可达”,就会得出错误结论。

1.3 列车与航线:计划类数据,必须引入时间切片思维

高铁列车信息和飞机航线信息,本质上都是“运输计划数据”。高铁车次会跟着铁路调图变化,通常一年有若干次全国性调图,每年1月、7月前后是调图窗口,但也会有临时调整。民航航线更是严格遵循航季规则:每年3月最后一个周日到10月最后一个周六是夏秋航季,10月最后一个周日到次年3月最后一个周六是冬春航季,航班计划一年换两季。

这意味着,数据里每一趟车次、每一个航班号,都需要带上“有效开始日期”和“有效结束日期”两个时间字段。否则你今天看到京沪线上的某个车次存在,三个月后调图它可能就被取消了,而你的历史数据里还留着它,就会造成“永远在飞的车次”这种失真表述。

关于列车时刻,还有一个新手容易踩的坑:出发和到达时刻要统一使用“北京时间”,并且最好以调度时刻表为准,而不是以第三方出行App的推算时刻为准。铁路调图后,App上的时刻往往要一两天才同步,直接抓取容易抓到过渡期的错数据。

所以我的建议是,把整个数据集拆成五张核心表来管理:

表名核心字段更新频率
线路表线路ID、线路名、线路等级、正线长度、设计时速低频,新增线路时更新
开通事件表线路ID、分段区间、开通日期、事件类型低频,新线开通时追加
列车时刻表车次、运行区间、线路ID、有效起止日期、发到时刻、停站数高频,每次调图更新
航线计划表航线ID、起降机场、航空公司、航班号、有效起止日期、班期中频,航季换季更新
机场/车站字典表站点ID、站点名称、城市、经纬度低频,新站启用时追加

2. 数据源与采集策略:公开渠道怎么组合,才能拼出一份可靠数据

数据源选型是整个项目里最影响成败的一环。我的原则是:开通时间找官方历史公告,线路属性找权威的开放性交通数据库,列车时刻表和航线计划分别从铁路运营企业官网和民航官方航季计划文件里抓取,第三方汇总平台只做交叉验证,不作为原始证据。

2.1 开通时间与线路信息:官方公告加数据库双线验证

高铁开通日期的第一手来源是开通当日的官方新闻通稿和发行机构发布的公告。这部分要看历史资料,效率不高,但准确度高。时间比较久的线路,还可以翻当时的杂志和报纸电子版,用关键词检索“线路名+开通”就能找到当时的报道。第三方百科站点上的开通日期只能作参考——我核对早期线路时发现,百科站点经常把“进入联调联试阶段”的日期误写为开通日期,容易把时间提前几个月。

线路的里程、设站数量、设计时速这些属性,最好从权威交通数据源获取,再人工抽样核对。做数据整理要有“交叉验证”的习惯:同一个字段至少有两个独立来源,如果两个来源打架,宁可先标记为空,也不要随便选一个填进去。我曾在某条中西部线路上发现里程差了20多公里,后来才发现是两个来源中有一个把延伸段的路程含进去了,如果不过滤掉,直接影响后续线网总里程的统计。

2.2 列车时刻与航线计划:工业化批量抓取

列车时刻和航线计划这种动态数据,靠人工一条一条抄录是不现实的。我的做法是写脚本从可用的开放数据源抓取,并按调图周期存档。

对于列车时刻,可以从铁路客票系统的页面接口里抓取指定车次的信息。核心参数是车次号和有效日期,返回的数据里包含发到站、出发到达时刻、历时和停站列表。抓取策略上我建议按线路来爬:先把线路表建好,再逐条查询这条线路上运行的车次,最后对每个车次解析发到时刻和沿途停站。这样做的好处是数据天然带上了线路ID,后续做“某线路日均班次”这类统计时直接按线路ID分组即可,不需要再做反向匹配。

对于航线计划,民航方面有公开的航季航班计划文件,按起飞机场分组列出每条航线的航班号、班期、起飞时刻和机型。逐段解析这类文件,加上全球机场字典里的经纬度信息,就能构建比较完整的航线表。机场字典我建议额外记录机场的IATA三字码和ICAO四字码,很多分析需要按三字码做关联。

2.3 一个可复用的采集框架

采集逻辑不复杂,但稳定性值得重视。我常用的框架分三层:

  • 第一层是“站点清单层”:维护线路清单、机场清单。
  • 第二层是“详情抓取层”:根据清单逐项请求详情,失败自动重试,并记录每个请求的时间戳。
  • 第三层是“落库层”:把抓取结果解析成标准字段结构,写入带版本号的存档文件。

存档格式上,我强烈建议同时保留“原始存档”和“规范化结果”两套数据。原始存档是当时页面返回的原始内容,规范化结果是你解析后的结构化表格。这样做的好处是,将来发现解析规则写错了,可以回看原始数据重新解析,而不必重新采集一遍。我的存档文件命名习惯是rail_schedules_2025_07.json这样的“类型+数据日期”格式,目录按年份归档,方便回溯。

3. 清洗与补全:最容易翻车的是日期冲突、口径不齐和站点改名

数据采集完成只是开始,真正耗时的是清洗。我常说,这份数据里真正可靠的部分,不是你采集到了什么,而是你如何处理弄不准的部分。

3.1 开通日期冲突的裁决规则

同一个线路的开通日期,在不同来源里经常差几天,甚至差几个月。我的处理规则很简单:优先采信官方开通运营新闻中出现的“于X月X日正式开通运营”表述;如果找不到官方新闻,采用首发列车的售票开售日期;再不行,采用第三方百科,但必须标注“待核验”状态。

还有一个经验值得分享:铁路新线开通前会先开启售票,开售日期通常早于正式开通日期1到3天。如果只凭新闻印象,很容易把开售日当作开通日。对于精确到“日”的分析,这种差值会产生系统性误差,所以我在事件表里加了一个“状态”字段,标记日期究竟是“官方确认值”还是“推算值”,后续使用方可以自行决定是否过滤推算值。

3.2 里程口径不统一的处理

前面提过里程有三个口径,实际清洗时我给每个线路记录加了一个“里程口径”备忘。凡是从同名数据库取来的里程,默认是正线长度;凡是学术论文或规划文件中出现的里程,往往用的是全线总长,需要额外换算。换算方法没有固定公式,最靠谱的办法是比对线路的起终点坐标,用大圆距离作为下界,再结合线路实际曲折程度做估算。如果线路的起终点不在同一纬度,大圆距离和实际运营里差一截是正常的,不要强行保持一致。

3.3 站点改名与坐标偏移:字典表承担“翻译”功能

高铁站名和机场名都存在改名现象。机场的IATA三字码稳定,但中文名会变;火车站则可能连站名都被整体调整。四类数据联查时,如果站点名称没统一,就会把同一实体拆成两行。解决办法是维护一张字典表,记录各站点在“标准名”之外的全部别名和新旧名称,并存储经纬度坐标。

坐标这个字段容易被忽略,但它实际上非常重要。有了坐标,才能做线网地图绘制、城市间大圆距离计算、站点位置纠偏等后续操作。坐标获取并不复杂,用通用地理编码服务即可,但要警惕机场和高铁站同名带来的编码错位——某城市同时有高铁站和机场,名称前缀相同,直接按名称编码很容易选错。我的做法是对每个站点人工核对一次坐标归属,之后才能批量入库。

3.4 历史空白数据的补全思路

2003年以前的数据大多能找到文字记录,但2003到2010年之间的列车车次和航班计划,很多当年的原始数据已经无法从网上获取了。对于实在补不齐的历史车次,我的建议是“存量优先,断点标记”:先把已经确定存在的车次整理出来,凡是不确定的部分,不要猜测,直接留空并加“缺失”标记。数据使用者看到缺口,至少知道这是数据源问题,而不是分析上的疏漏。

补全历史数据时有一种性价比很高的方式:用旧版地图和旧时刻表书。旧时刻表书虽然扫描质量参差不齐,但包含完整的车次、停站和票价,是列车时刻历史版本的最佳回顾来源。我在整理2015年前的列车数据时,参考了若干本旧时刻表书,补齐了不少调图后消失的车次。

4. 数据结构化与落地:主键怎么定,决定了多表关联时会不会产生脏数据

前面五张表的框架确定之后,最关键的是主键设计和表间关联方式。主键选不好,后面做任何联合查询都可能遇到重复数据。

4.1 线路表和开通事件表的主键

线路表的主键我用的是自定义的线路ID,规则是“线路名拼音缩写+数字序号”,例如某条东西向骨干线的ID是GD01这样的形式。这个ID一旦确定就不再改变,即使线路后来延长或调整了首末站。开通事件表则以“线路ID+分段区间”为联合主键,确保同一线路的每个开通事件只有一行。注意,分段区间要按标准化站名记录,不能一会儿写全称一会儿写简称。

4.2 列车时刻表和航线计划表的主键

列车时刻表的主键是“车次+运行日期+线路ID”。这里有个实际场景:同一车次在不同日期可能运行不同的交路,偶尔还会因为临时调整在特定日期停运。所以一张完整的列车时刻表,应该以“车次号+有效日期”为粒度,而不是简单以车次号为唯一键。

航线计划表的主键更复杂。同一个航班号在不同季节可能起点终点互换,比如某航班号冬春季执行A到B航线,夏秋季改飞B到C,这在支线航线上并不罕见。所以航线表的主键是“航空公司+航班号+有效起止日期+航线方向”。千万别只拿航班号当唯一键。

4.3 增量更新:现状表加历史日志

动态数据不是一次性建完就不用管了。我采用的是一个简单稳妥的更新模式:每个调图周期结束后,生成一个新版本的“现状表”,同时建立一张“变更日志表”。

变更日志表的字段包括:车次或航班号、变更类型(新增/取消/时刻调整/区间调整)、旧值摘要、新值摘要、生效日期、数据来源。这张表的价值很大,后续做“某线路高铁班次逐年增长情况”“某航线航空公司是否持续加密”这类分析时,不用靠对比两个版本的现状表来猜,直接在变更日志里就能查。

增量更新的频率不需要高于调图频率。铁路调图通常一年几次,民航一年两次换季。我在日历上设置了固定提醒:每年1月、7月检查铁路调图,3月和10月的最后一个周日检查民航换季,其余时间不需要频繁抓取,减少数据污染风险。

4.4 校验规则:上线前必须跑一遍检查清单

数据入库后,我会跑一遍自动校验脚本,检查以下规则:

  • 线路表中的里程字段必须大于0,且数值处于合理范围内。
  • 开通事件表中的开通日期不能晚于数据生成的当前日期。
  • 列车时刻表中,同一车次同一运行日在同一线路ID下不能出现两次以上。
  • 航线计划表中,机场三字码必须存在于机场字典表,否则可能是抓取解析出了问题。
  • 每张动态表的有效起止日期区间不能重叠,重叠说明更新日志有问题。

这些校验规则看着简单,但确实帮我抓住了很多细节错误。有一次跑完校验发现某个航班号下同时存在两个不同航线的记录,查下来才发现是航季交替时新旧计划重叠了几天,后来靠有效日期区间过滤解决了问题。

5. 这套数据能用来做什么:从时间轴动画到高铁与航空的竞合观察

数据整理完成的最终目的,还是要服务于具体问题。我结合自己做过的一些分析场景,给你几条思路。

5.1 时间轴动画:看高铁线网如何逐年长成

有了开通事件表,按年份分组统计新开通线路数量,就能画出一张“中国高铁线网演化”的时间轴动画。做法很简单:先按年份汇总新开通线路,再逐年累加线网总里程。你会发现2008到2015年之间是线网快速成长期,之后逐步进入加密和补空白阶段,近几年的新增里程集中在之前没有覆盖的区域。动画不要刻意追求炫酷,关键是把时间维度体现出来,再叠加线路等级和设计时速信息,就能直观看到中国高铁从试点线路走向成网的过程。

5.2 高铁与航空的竞合视角

把列车时刻表和航线计划表放在一起,可以做很有意思的交通方式对比。比如选定一条1000公里左右的中程线路,分别统计高铁班次数量和航班班次数量,再按年份看两者比例变化。通常可以看到前几年航班占主导,高铁开通后班次快速增加,航班密度下降的过程。做这类分析时,要注意单位的统一:高铁统计的是“日开行班次”,民航统计的是“周执行班次”,要先换算成同一时间口径再做对比,否则柱状图会误导人。

5.3 一个最简单的可跑通示例

如果你只是想快速验证数据质量,可以先做一步最基础的操作:读入线路表和开通时间表,按年份汇总新开通线路条数和总里程,画一张简单的柱状图。参考代码如下:

import pandas as pd lines = pd.read_csv("rail_lines.csv") events = pd.read_csv("opening_events.csv") df = pd.merge(lines, events, on="line_id") summary = df.groupby("opening_year").agg(新开通线路=("line_id", "count"), 新增里程=("length_km", "sum")) print(summary)

这个代码不需要任何复杂依赖,pandas就够用。跑通之后,再从列车时刻表里按线路ID统计日班次,你就能对每条线路的繁忙程度有一个基本印象。数据质量好的话,线路里程和班次数之间应该有正相关关系,如果出现某条超长线路日班次反而很少,往往说明这条线路尚处于加密前阶段或客流量有限,这个偏差本身就是有分析价值的信号。

6. 数据质量的边界与维护建议:越早越粗糙,越快越要存档

最后聊几句我在反复迭代中形成的认识。这份2003到2025年的数据,时间跨度非常大,越早的数据越稀疏,可靠性也越低。早期列车的车次信息很多只能从旧时刻表期刊里找,班次记录的完整性不如近十年。这并不代表数据不能用于分析,而是要求你在下结论前先搞清楚数据覆盖率的边界。

一个典型场景是计算“某年全国高铁总发送量”,如果你只依赖列车时刻表推算运力,再用平均载客率估算人数,误差会被放大。正确做法是只用官方发布的年度发送量统计,列车时刻表只用来推算“开行规模”而不用于推算“人数”。数据工具用对了边界,结论才有参考价值。

维护方面,我的建议是不要追求实时同步。铁路和民航的计划数据更适合“版本化存档”的方式:每季度或每次调图后留一份完整的快照,而不是今天改一个车次、明天改一个航班。快照式的存档让历史回溯变得简单,也让新增数据保持稳定。从2003年整理到现在,我手里一共有几十个版本快照,每次做趋势分析时,直接拿出对应年份的版本即可,完全不需要担心后来的更新污染历史结论。

我在实际使用中还有一个体会:这套数据的最大价值,不只是给了你一条条线路和航班,而是让你能围绕“某地到某地到底有哪些交通选择”这个朴素问题,搭建一套可重复计算的分析框架。当你把四类数据用一致的主键关联起来,很多看似孤立的数字就串起来了。后续你要扩展更多地域范围或者补充公路数据,也只是在这个框架上继续挂载新表而已。

最后分享一个小技巧:每周抽十分钟,把本周采集过程中遇到的所有异常记录单独存到一个“异常清单”文件夹里。无论是站点改名、车次停运、还是航线跳变,都留一条日志。几个月后你回头看,这份异常清单往往比数据本身更能帮你理解交通网络的真实变化规律。整理数据的人,不能只盯着数字,更要盯着数字背后的变动痕迹。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询