近日折腾了 TfL API,特将经验总结如下。

没有卵用的 API Key

文档称调用 API 需要提供 Key,然而实际上并不需要。只是如果您不提供 Key 就会出现 Throttle。可是这个 Throttle 似乎是根据 session 来的,清理 cookie 或者一开始就不要带 cookie 即可。官方 Single Fare Finder 严格遵守规定提供了 Key,但是请求是从前端发出的,大家都能看到。

Overground 究竟有几个车站

API 认为 Overground 有 111 个车站,而 TfL 网站的这个页面却认为有 112 个。网上只有 112 个站的说法,并没有找到 111 的相关信息。我对着 May 2019 的 Tube map 数了数,只数出了 111 个。

Update: 破案了,Geoff Marshall 在视频 All 112 Overground Stations in the Fastest Time 中介绍了第 112 个站 Battersea Park。

TfL Rail 的 Whitechapel 站

众所周知,TfL Rail 的 Liverpool Street 和 Stratford 站之间并没有其他车站。但是 TfL 的 API 和这个页面都认为中间有 Whitechapel 站。虽然该站将会出现在 Elizabeth Line 上,但目前并没有 TfL Rail 的列车停靠于此。

不同接口数据不一致

Route API 返回的数据有很大问题。比如 /Line/c2c/StopPoints 返回 26 个站而 /Line/c2c/Route/Sequence/all 只返回 24 个站。其中正好少了在 Fare Zone 中的 Ockendon 和 Chafford Hundred。Route API 中的 Reading Rail Station 是 910GRDNG4AB,与 StopPoint API 和 Fare API 用的 910GRDNGSTN 不一致。

Fare API 也有一些问题,比如居然没有 Bakerloo 的 Edgware Road 站(940GZZLUERB)。

如何圈定能 PAYG 的车站

从 API 上拉下来的车站列表非常的庞大,其中有许多并不在伦敦,比如 Edinburgh Rail Station。那么如何剔除这类车站呢?

尝试1:从 API 获取整个网络存为无向图,手动输入地图上标注的支持范围,算出车站们

比如:所有的 Underground 站; Gatwick Airport 和 Brookmans Park 之间的 Thameslink 站。

但是这是不靠谱的,因为地图不靠谱。Thameslink 官网的这份地图还认为 London Bridge 和 London Blackfriars 之间不通。较新的这份地图也只把区域标到了北至 Radlett 和 Brookmans Park 的地方。而事实上,早在 2019 年 10 月,Luton Airport 就已经举行仪式热烈欢迎 Contactless 的到来了,另一支线路的也早就扩展到了 Welwyn Garden City,而且随时可能爆出再次扩张的新闻。

同时你也不要觊觎从 TfL API 拿到的铁路网数据,这也不靠谱。比如现在上面还有 Virgin Trains East Coast 和 East Midlands Trains,上面的 Thameslink 也不通 Cambridge。

想法2:从 API 获取车站的地理坐标,与什么东西比一比

一想就知道不靠谱。拿坐标与什么东西比呢?Greater London 的边界吗?TfL Empire 早就扩张到 Greater London 外面了。

想法3:抄 Single Fare Finder

那么 TfL 自己的 Single Fare Finder 是怎么做到只选择支持范围内的车站的呢?看了一眼请求发现它没有使用特供接口,而是使用了公开 API。这个接口提供从用户输入自动补全车站的功能,有一个 faresOnly 参数,钩上即可限制在 TfL Empire 边界内。我又看了看其他 API,并没有提供这个参数。所以更准确地说,并不是没有使用特供接口,而是他们把特供接口公开出来了。

那么我就可以先拿到一大堆车站,然后用名字去这个接口上撞,看能不能撞到即可。这一撞,又撞出了几个问题。

问题4:出现了不在线路网里的车站

比如 New Cross。虽然有 New Cross 这个车站,但是系统里把路网挂在了 New Cross ELL Rail Station 上。问题不大,忽略。

问题5:诶有个查询返回了奇怪的东西

在爬去数据时,我收到了一条 JSON parse error。第一反应是触发了 Throttling,返回了错误页面。然而并没有,仔细观察后我认为应该是我在搜索 Bingham Rail Station 的前缀 Bin 时因为敏感词 bin 撞到了什么安全机制。前缀多来几个字就好了。

问题6:依然少了一些车站

即便是 API 拉下来的巨大车站列表,也少了一些站,比如 Ockendon。

想法7:从 Rail & Tube Map 中提取车站

Rail & Tube Map 2019 年 12 月才刚刚更新,里面的车站列表应该是完整的,故应该可以提取全部的车站名称去 Fare API 上撞。

问题8:还是少了一些车站

地图上有 King’s Cross 和 St Pancras 但没有 King’s Cross St Pancras。这个问题不大,Fare API 会找到它。

问题是,地图上有 Luton Airport Parkway 可是第二页的车站列表里居然没有。猜测列表里不包含 Outside fare zones 区域的车站,然而 Reading 在里面。更奇怪的是 Radlett 在 2019 年 5 月版地图上的车站列表中,现在却不见了。

尝试从地图而不是地图附带的车站列表获取车站,发现 pdf 加了密码不让复制 / 导出。于是找了一个空 pdf 和它合并,绕过了限制。但是最终效果还是不尽人意,站名与站名之间没能很好的区分开。