想给业余项目加个港口查询功能,却发现现成的免费干净列表哪儿都找不着——要么收费墙拦住,要么登录才能看,要么就是十几年前的僵尸数据。一位开发者碰了这钉子后,决定自己动手。结果一发不可收拾,最后搭出了一个叫“The Port Index”的网站:3804个海港加9640个机场,免费、无需注册,整套数据还能一键导出成CSV或JSON。他自己把踩过的坑、学到的教训都整理了出来,干货含量不低。
这套数据没花一分钱授权费,全来自公共领域。他把三个公开来源拧在一起:美国政府的《世界港口索引》(NGA World Port Index,编号Pub 150),覆盖约4000个港口,每个港口挂着上百个代码化的属性,从水深、最大可停靠船型,到引航要求、设施说明一应俱全;联合国欧洲经济委员会的UN/LOCODE地点代码;以及OurAirports这个公共领域数据库,9千多个机场的IATA/ICAO代码、跑道长度、海拔高度都在里头。他的体会很直白:公开数据到处都是,真正值钱的是让数据变得好用。
很多人都以为“解析个CSV能有多难”,真正干起来才知道,坑全藏在数据清洗阶段。他举了几个差点让他翻车的例子。一是带换行符的引号字段。《世界港口索引》的CSV里头,有些值跨多行,文本中间夹着换行符。用简单的按行split处理,直接就把一行记录撕得七零八落,变成一堆没意义的碎片;必须上正经的CSV解析器,老老实实把引号内的换行当场内嵌内容才过关。
另一个让人哭笑不得的问题出在近海油码头。这些站点列出的深度动不动就900米以上,乍看像超级深水港,其实是系泊浮筒处的海底深度,根本不是港池水深。要是直接拿来排“全球最深港口”,整张榜单会被一堆外海单点系泊浮筒霸占,真正的深水港反倒不见踪影。他只好写规则把这些“伪深水”给筛掉。还有一个常见陷阱:原始源把0当“未报告”。你如果不过脑子就信了,会自信满满地给大半个地球的港口标上“航道深度0米”的荒唐结果。
从枯燥数字里榨出一点实用判断力,是他觉得最有意思的部分。一个光秃秃的14.5米水深没什么可说的,但如果自动推断出“这个泊位能停巴拿马型船,不过好望角型就够呛”,对用的人就立马有了意义。于是他加了一层简单的推理:把港口水深映射到可容纳的船舶等级;同时给机场跑道长度做了航空版——跑道长度对应起降的飞机类型。这样浏览时就多了一重筛选维度,不是干巴巴的查找表了。
他还折腾出一个让他自己特别上瘾的交叉链接结构。每个港口页面都会列出距离最近的机场,反过来每个机场页也会列出最近的海港。这些地理关联是在构建时靠简单的空间网格预先算好的,不是实时查询。正是这种互相引用的网状结构,让一个纯粹的目录变成了可以四处探路的活地图,从一个点能不断跳到另一个有意思的点。
整个网站约一万四千个页面,背后没有服务器、没有数据库,跑起来几乎不要钱。他用的是Next.js的完全静态生成模式。generateStaticParams遍历整份数据集,在构建阶段把每个港口、每个机场的页面全预渲染好,部署到CDN就完事,运行时零成本,速度还飞快。套用他的说法,“没后端,也没账单焦虑”。
不过最让其他开发者觉得值回票价的,可能是他在SEO上撞的墙。程序化生成的站点,一不留神就把上万个模板化页面全扔进Google索引,结果会被系统标记成“规模化/薄内容”,广告申请都因此被拒。他踩坑后的补救办法是主动做减法:每个垂直领域只让质量最高的约400个页面保持在索引和站点地图里,长尾部分主动拦在搜索门外。牺牲一点收录量,换来整体站点质量评估过关,这笔账他划得来。
热门跟贴