简介:这份全球飞行航线数据以Shapefile格式组织,面向GIS开发者、航空交通研究者及数据可视化爱好者,可用于航线网络分析、航班流量统计与地理空间可视化。压缩包共15个文件,约8.01MB,核心为两个.shp几何文件,配套.dbf属性表、.prj投影定义、.shx/.sbn/.sbx索引文件以及.xml元数据,便于在ArcGIS、QGIS等软件中直接读取和高效查询。已有742人学习下载。数据覆盖全球主要航线,包含起止机场坐标、航路点等几何信息,并附带.qix快速索引,能够支撑航线密度分析、机场间距离测算、高峰时段特征挖掘等场景;采用通用投影定义,方便与人口、经济等专题数据叠加,探索航空交通与区域发展的关联。使用时需确保文件完整,并遵守数据许可协议。 之前做了个民航数据可视化的小项目,想找一套现成的“全球飞行航线数据shp格式”文件来当底图。网上一搜,整理好的shp确实不少,但下载下来多多少少有点问题:坐标系对不上、字段缺胳膊少腿、打开属性表全是乱码,有的干脆就是拿线段瞎画的。后来我干脆自己从OpenFlights的原始CSV数据开始整理,一路上把机场表、航线表、格式转换、坐标系这些坑全踩了一遍,最后总算在QGIS里渲染出一张像模像样的全球航线网。
这篇东西就把整个过程里最值得记录的经验写出来。如果你也需要用shp格式的航线数据做分析或者出图,不管你是GIS从业者、数据分析师,还是刚接触地理数据的初学者,这套流程和踩坑记录应该能帮你省掉不少折腾的时间。
1. 航线数据到底是什么样的GIS数据
1.1 三类核心数据拼出完整航线网络
全球飞行航线数据在GIS里看,本质上是一张“有向网络图”。拿到一份比较完整的航线shp,通常会包含机场点、航线段两类要素,而支撑这些几何的,是机场、航空公司、航线三个维度的信息。机场表记录每座机场的IATA三字码、ICAO四字码、城市、国家、经纬度、海拔;航空公司表记录航司代码和名称;航线表则是核心中的核心,每条记录都代表一个航班连接,包含起飞机场、降落机场、所属航司、经停次数等字段。
如果只是要一张能看的图,拿现成的航线shp也能出效果。但如果要做城市连接度分析、航线网络密度统计这类正经分析,最好还是自己从原始数据整理。因为很多网上流传的shp在整理时,会把双向航线合并成一条无向线段,也会丢掉经停信息,这对后续的分析影响很大。自己处理一遍,至少数据质量是可以保证的。
在实际用shp存航线数据时,常见的做法是把每条航线存成一条LineString线段,起终点坐标直接取机场经纬度。机场数据单独存成一个点要素的shp,两者通过机场代码关联。这个结构简单直接,也是目前大多数公开航线数据集的通用方案。
1.2 shp不是“一个文件”,而是一套文件
新手最容易栽的跟头,就是以为shapefile是一个单独的文件。实际上shp格式是一组文件抱团组成的,至少包含三个核心文件,缺一不可。
- .shp:主文件,存几何图形信息,也就是那些点和线
- .shx:形状索引文件,帮程序快速定位图形位置
- .dbf:属性表文件,存每条要素对应的机场名、航司代码等非空间信息
除了这三个,还经常能见到.prj(坐标参考文件)、.cpg(字符编码文件)、.sbn和.sbx(空间索引)这些配套文件。很多人从网上下载或者U盘拷文件,只拖了后缀是.shp的那个,结果拿回来在GIS软件里怎么都打不开,报错提示找不到配套文件。这就是没搞清楚shp的“合租模式”造成的。
你可以把shp格式理解成一套合租房的钥匙、门牌号、住户清单,三个缺一不可。.shp管“房子长什么样”,.shx管“哪把钥匙开哪扇门”,.dbf管“房子里住着谁”。拷贝的时候,把这三个文件放在同一个目录下,名字保持一致,才算完成了一次完整的文件转移。
2. 航线数据从哪里来
2.1 主流开源数据源怎么选
做全球航线数据,绕不开的开源数据源主要有三个:OpenFlights、OurAirports,以及各类GIS数据社区整理好的现成shp。
OpenFlights是我最推的起点。它的机场表(airports.dat)和航线表(routes.dat)都是CSV格式,字段齐全、更新频率高,而且允许非商业用途下载使用。其中routes.dat大概有6万多条航线记录,覆盖全球大多数定期航班,拿来做可视化绰绰有余。OurAirports则侧重于机场点数据,每个机场的几何信息更规范,但航线数据不是它家的强项。
网上也有很多已经处理好的“全球航线shp”可以直接下载,这类数据对只需要快速出图的人来说很方便。但我的建议是,下载之后务必先检查三件事:坐标系是不是WGS 84、字段含义是否清晰、航线方向有没有被合并。如果这些答案都不确定,宁可多花点时间自己整理,也别直接拿去交差。
2.2 用OpenFlights原始文件自己组装航线shp
自己整理没有想象中那么复杂,核心思路就是:把OpenFlights的CSV航线表和机场表关联起来,按起终点经纬度生成线段,再导出成shp。整个过程用Python写个脚本就能完成,大概三四十行代码。
先到OpenFlights官网下载airports.dat和routes.dat两个文件。机场文件里包含机场ID、名称、城市、IATA码、ICAO码、经纬度等字段;航线文件里包含航空公司、起飞机场、目的机场、经停次数、航班设备等字段。注意这两个CSV里有一部分字段本身带有逗号,比如机场名称,所以读取时不要用简单的split(","),要用csv模块或者pandas来处理。
下面是我整理时用的脚本,逻辑比较直白:
import geopandas as gpd import pandas as pd from shapely.geometry import LineString # 1. 读取机场表,构建 IATA 三字码 -> 经纬度 的映射 airports = pd.read_csv( "airports.dat", header=None, names=["id", "name", "city", "country", "iata", "icao", "lat", "lon", "alt", "tz", "dst", "tz_db", "type", "source"], engine="python", escapechar="\\", ) airport_coord = {} for rec in airports.itertuples(): iata = str(rec.iata).strip() if iata and iata != "\\N": try: airport_coord[iata] = (float(rec.lon), float(rec.lat)) except ValueError: continue # 2. 读取航线表,生成 LineString routes = pd.read_csv( "routes.dat", header=None, names=["airline", "airline_id", "src", "src_id", "dst", "dst_id", "codeshare", "stops", "equipment"], engine="python", ) features = [] for rec in routes.itertuples(): # 只保留直达航线(经停为0),控制数据量 if str(rec.stops).strip() not in ("0", "0.0"): continue src = str(rec.src).strip() dst = str(rec.dst).strip() if src not in airport_coord or dst not in airport_coord: continue if src == dst: continue line = LineString([airport_coord[src], airport_coord[dst]]) features.append({ "geometry": line, "properties": { "airline": rec.airline, "src": src, "dst": dst, "stops": rec.stops, } }) # 3. 生成 GeoJSON(中间格式,方便预览) gdf = gpd.GeoDataFrame.from_features(features, crs="EPSG:4326") gdf.to_file("routes.geojson", driver="GeoJSON") print("生成航线数量:", len(gdf))脚本跑完,会得到一个routes.geojson文件,里面有五六万条航线线段。GeoJSON在网页端、QGIS里都能直接打开预览。如果只是自己用,这个中间格式完全够;如果要求交付shp格式,再用命令行转一下就行。
注意:脚本里我主动过滤了经停不为0的航线,因为保留所有中转航线会让数据量暴涨,而且很多中转航线的起终点并没有实际连接意义。如果你做的是全量航线网络分析,可以删掉这个过滤条件,但文件体积和渲染性能要做好心理准备。
3. GeoJSON转shp格式:三种工具一次讲透
GeoJSON转shp算是GIS数据日常里最高频的操作之一,尤其现在很多在线数据源默认提供的是GeoJSON格式,而传统GIS工具链、老旧的数据库系统、部分外包交付需求还是只认shp。我整理一下三种最常用的转换方式,覆盖图形化操作、命令行批量处理、Python脚本三种场景。
3.1 QGIS图形界面导出,适合一次性操作
如果你的数据量不大,或者只是偶尔转换一次,用QGIS的图形界面最省心。操作路径很直观:把GeoJSON文件拖进QGIS,右键图层,选择“导出”->“要素另存为”,然后在格式里选“ESRI Shapefile”,文件编码记得选UTF-8,坐标系保持原样就行,QGIS会自动帮你生成整套shp文件。
这里有一个容易忽略的选项:在导出对话框里可以设定字段类型和长度。如果GeoJSON里的数字字段被识别成了字符串,可以趁导出时手动改成整数型或浮点型,避免后续做统计时还得来回转换。图形界面直观是优点,但同时也意味着每次转换都要手动点好几下,如果一天要转几十个文件,效率不太行。
3.2 ogr2ogr命令行批量处理,适合重复性任务
批量转换、要写进发布流程、或者服务器上没有图形界面的情况下,ogr2ogr才是正统解法。它是GDAL/OGR工具集里的转换命令,几乎所有GIS环境里都有。
最基本的转换:
ogr2ogr -f "ESRI Shapefile" -lco ENCODING=UTF-8 routes.shp routes.geojson这条命令指定了输出格式为ESRI Shapefile,输出文件的编码为UTF-8。如果不加-lco ENCODING=UTF-8,有些环境下生成的dbf默认编码可能不是UTF-8,在QGIS里打开属性表就会看到中文乱码。
如果需要顺带转换坐标系,比如从WGS84经纬度转成Web墨卡托:
ogr2ogr -t_srs EPSG:3857 -f "ESRI Shapefile" -lco ENCODING=UTF-8 routes_merc.shp routes.geojsonogr2ogr还有一个实用参数是-sql,可以在转换的同时做字段筛选、条件过滤,相当于在转换环节就把数据清洗掉一部分。比如只想保留某几家航司的航线,完全不用先写Python脚本处理,直接一条SQL语句搞定。这个命令批量处理几十个文件也就是一个for循环的事,建议所有经常和数据打交道的人都把它用熟练。
3.3 Python geopandas脚本化,适合融入数据管道
如果整个数据流程本来就是用Python搭的,那直接用geopandas来转最自然。geopandas底层用的就是GDAL,所以写起来很简洁:
import geopandas as gpd gdf = gpd.read_file("routes.geojson") # 可以在这里做字段筛选、数据清洗 gdf = gdf[["airline", "src", "dst", "stops", "geometry"]] gdf.to_file("routes.shp", encoding="utf-8", driver="ESRI Shapefile")用geopandas转shp有个好处:中间的清洗、字段名调整、坐标系转换可以顺势一起做掉,整个数据管道用一份Python代码就管住了。缺点是首先得把geopandas、shapely这些依赖装上,如果你只是偶尔转一次文件,装这一堆依赖不太划算。
三种方式的选择逻辑其实很简单:一次性操作用QGIS,批量干净利落用ogr2ogr,所有流程都是自动化脚本用geopandas。没有一种方式是绝对最好的,只看哪个跟你的工作流更匹配。
4. 坐标参考、编码和字段这些坑
4.1 坐标系:WGS84和Web墨卡托别混用
全球航线数据的坐标基本都基于WGS 84地理坐标系,也就是EPSG:4326,单位是经纬度。这个坐标系简单直观,但有个麻烦:它的单位不是米,所以拿它直接算距离、面积会得到错误结果。
很多在线地图底图用的是Web墨卡托投影(EPSG:3857),单位是米。如果你把EPSG:4326的航线shp直接叠加到EPSG:3857的底图上,QGIS、ArcGIS这些软件会自动做动态投影,显示上没问题,但一旦你执行空间连接、缓冲区分析这类计算,软件就会弹出坐标系不一致的警告,处理不好就出现几十上百公里的位置偏移。
我的习惯是:底图和分析图层的坐标系必须统一。如果只是出图展示,直接用WGS84也够用;如果要计算距离或叠加到在线底图,先把数据转成EPSG:3857,再往下走流程。
另一个细节:机场点的经纬度在属性表里通常会以“lat”“lon”两个字段存在,但shp文件本身的几何信息里也有一份坐标。有的新手会搞混这两种坐标,以为改了属性表里的经纬度字段,点就会移动,实际上几何信息完全没变。在GIS里,属性表只是“说明书”,几何才是真正的“地图”。
4.2 dbf字段和编码的“隐藏规则”
shapefile的dbf属性表用的是老式的dBase格式,有几个历史遗留的硬性限制,不少人在这个上面吃过亏。
第一,字段名长度最多10个字符。GeoJSON里如果有个字段叫“international_code”,转成shp后会被自动截断成“internatio”,同时可能因为字段名重复而报错。这个没有太好的解决办法,只能尽量把字段名设短一些,像airline、src、dst这种长度就合适。
第二,dbf字段类型对中文支持不友好。虽然可以使用UTF-8编码,但有些老式GIS软件只支持GBK甚至Latin-1,导致属性表里的中文变乱码。解决方案是在保存shp时统一指定编码。用ogr2ogr转就加-lco ENCODING=UTF-8,用QGIS导出就在编码下拉框里选UTF-8,geopandas则是encoding参数里写utf-8。
第三,shp不支持一个文件里混合多种几何类型。如果你生成的GeoJSON里既有LineString又有Point,直接转shp会报错;就算某个要素几何类型为MultiLineString,和普通LineString混在一起也不被接收。所以转格式之前务必检查几何类型是否统一,一种类型一个文件。
shp本身也有2GB的体积上限,而且是非压缩格式,航线数据量大、字段又多的时候,文件体积增长很快。我的建议是:中间处理和预计算阶段优先用GeoPackage格式,这个格式支持压缩、没有2GB限制、一个文件打包所有图层;只有最终交付或对接外部工具时才转成shp。很多踩坑踩到怀疑人生的项目,把格式换成GeoPackage之后问题直接消失。
5. 航线数据可视化与典型应用
5.1 用QGIS画一张航线网络图
有了全球航线shp,第一件想做的事肯定是把它画出来看看效果。QGIS里操作很简单:把shp直接拖进去,调整样式就行。航线数据量大,默认的实线样式会糊成一团黑,需要手动设置透明度、线宽和颜色。
我一般把线路颜色设为浅蓝色,透明度调到50%左右,线宽设成0.3毫米。这样密集区域能看出高亮的核心走廊,稀疏区域也不会变成单一黑线。如果想要表达航线方向,可以在符号化的“线”选项卡里选择“简单线”并添加箭头标记,箭头会沿着线段方向绘制。不过全球几万条航线全带箭头,渲染压力有点大,一般只对局部子集开启。
渲染完成后,能明显看出全球航线网络的基本骨架:欧洲、北美东部、东亚、中东以及跨太平洋航线最为密集,南美、非洲内部航线相对稀疏,大洋洲则呈现出典型的“孤岛-干线”结构。这种直观的视觉信息,是任何统计图表都替代不了的。
5.2 航线数据的分析延展
航线shp不是只能拿来出图,它能做的分析非常多。最简单的应用是城市连接度分析:以机场点作为节点,统计每个机场作为起降点的航线数量,就能得到这座城市的航空网络辐射能力。这里要注意的是,航线shp里A到B和B到A通常是两条记录,做有向网络分析时要保留方向语义;做无向连接度统计时则需要先合并双向航线。
再往上走,可以用NetworkX这类图分析工具,把shp里的航线读取为网络的边,计算度中心性、介数中心性等指标,识别哪些城市是真正的枢纽节点。把航线数据和人口、经济数据叠在一起,还能做很多有趣的交叉分析,比如“某区域航线密度与GDP的关系”“机场与城市群发展的协同程度”等等。
对做交通、旅游、物流方向的人来说,全球航线shp是一个基础数据底座,很多业务问题的探索都可以从这张网络开始。而对数据可视化爱好者来说,把全球航线渲染成一张带流动感的网络图,本身就是一件很有成就感的事。
6. 常见问题排查与避坑经验
6.1 常见问题排查速查表
下面这些问题是我在整理数据过程中实际遇到过的,也问过身边不少同行,整理成了一份速查表,遇到类似情况可以对照排查。
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 打开shp提示缺少文件 | 只拷贝了.shp,缺少.shx和.dbf | 确保三个核心文件同目录同名 |
| 属性表中文乱码 | 保存时未指定UTF-8编码,或打开时编码识别错误 | 用QGIS数据源管理器指定UTF-8,或加-lco ENCODING=UTF-8重转 |
| 图层显示位置明显偏移 | 坐标系或.prj文件丢失,原数据不是EPSG:4326 | 确认数据源坐标系,用“定义投影”或重投影修复 |
| 航线全部变成点 | 几何类型不统一,LineString被转为Point | 检查几何类型,shp一个文件只支持一种几何 |
| 转换shp时字段被截断 | dbf字段名上限10个字符 | 转换前把字段名缩短到10字符以内 |
| 导出shp后文件特别大 | 字段过多、几何过于复杂、未过直接航线过滤 | 精简字段,过滤经停航线,或先用GeoPackage保存 |
| 航线表里有很多重复记录 | 同一航线由不同航空公司执飞,属于正常情况 | 按需去重,但保留航司维度会丢失部分信息 |
6.2 几条实用的避坑经验
最后分享几条经验,都是我踩过坑之后总结出来的。第一,从网上下载的任何shp,拿到手第一件事就是在QGIS里查看坐标参考信息,不要直接往下游工具里丢。很多看似正常的shp,坐标系是未定义状态,后续分析全乱。
第二,shp属性表的字段名尽量用英文短名,不要存中文长文本。虽说技术上支持,但不同软件对中文支持的差异极大,换一个环境就可能乱码。要做中文映射,宁可在后续展示图层时做字段别名,也别在shp里硬存中文。
第三,千万记得保留数据源文件和处理脚本。原始数据、中间GeoJSON、最终shp,这三层文件建议都留一份。你当时觉得没有用的中间文件,很可能过一个月之后改需求时又要用。我在整理航线数据时就是这样,第一次只留了最终的shp,后来想加一个机场时区字段,发现还得从头处理原始数据,教训相当深刻。
我个人实际操作下来的体会是:全球飞行航线数据这套东西,真正难的不是“找到数据”,而是“把数据处理成自己能用、还敢用的状态”。如果你只是画一张示意图,网上的现成shp可以应付;但只要你打算做量化分析,或者对数据做任何形式的二次加工,那就老老实实从原始CSV开始走一遍。自己整理一遍之后,后续出图、分析、交付整个链路都顺很多。
本文还有配套的精品资源,点击获取