关于 scandinavia-transit
scandinavia-transit 是用于查询挪威、瑞典和丹麦境内地面交通的技能,面向行程规划者。它汇集三国的公共交通 API,可查询路线、班次及丹麦票价信息。
主要功能
- 01挪威交通路线与班次查询
- 02瑞典交通路线与班次查询
- 03丹麦交通路线与班次查询
- 04站点及地点搜索
- 05丹麦票价与区域信息
适用场景
- 01规划奥斯陆至卑尔根的行程
- 02查询瑞典城市间的火车路线
- 03查找丹麦车站出发信息
- 04比较丹麦路线及票价区域
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ borski/ travel-hacking-toolkit --skill scandinavia-transit安装后在 Claude Code 中输入/scandinavia-transit确认已加载。
详细介绍
斯堪的纳维亚交通技能
使用挪威、瑞典和丹麦的国家交通 API 搜索地面交通(火车、巴士、渡轮)。
数据来源:
- Entur(挪威) — 面向所有挪威公共交通的开放 GraphQL API
- ResRobot(瑞典) — Trafiklab 提供的 REST API,覆盖所有瑞典公共交通
- Rejseplanen(丹麦) — REST API(HAFAS),覆盖所有丹麦公共交通,包含票价
挪威:Entur(Journey Planner v3)
开放的 GraphQL API。无需密钥(但必须提供客户端名称标头)。覆盖挪威所有公共交通:Vy 火车、巴士、渡轮、有轨电车、地铁。60 多家运营商。
行程搜索(奥斯陆至卑尔根示例)
curl -s -X POST "https://api.entur.io/journey-planner/v3/graphql" \
-H "Content-Type: application/json" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" \
-d '{"query": "{ trip(from: {place: \"NSR:StopPlace:59872\"}, to: {place: \"NSR:StopPlace:548\"}, numTripPatterns: 5) { tripPatterns { startTime duration legs { mode expectedStartTime expectedEndTime fromPlace { name } toPlace { name } line { publicCode name authority { name } } } } } }"}' | jq '.data.trip.tripPatterns[] | {start: .startTime, duration_min: (.duration / 60), legs: [.legs[] | {mode: .mode, from: .fromPlace.name, to: .toPlace.name, line: .line.publicCode, operator: .line.authority.name, depart: .expectedStartTime, arrive: .expectedEndTime}]}'
查找站点 ID
站点 ID 格式为 NSR:StopPlace:XXXXX。可通过 Geocoder 查找:
curl -s "https://api.entur.io/geocoder/v1/autocomplete?text=Oslo%20S&size=3" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" | jq '[.features[] | {name: .properties.name, id: .properties.id, type: .properties.layer}]'
主要站点 ID
| 城市 | 站点 ID | 名称 |
|---|---|---|
| Oslo S | NSR:StopPlace:59872 | Oslo S |
| Bergen | NSR:StopPlace:548 | Bergen stasjon |
| Stavanger | NSR:StopPlace:4130 | Stavanger |
| Trondheim | NSR:StopPlace:41742 | Trondheim S |
| Bodo | NSR:StopPlace:49484 | Bodo stasjon |
使用 Geocoder 查找任意站点。机场、渡轮码头和巴士站也适用。
出发时刻表
curl -s -X POST "https://api.entur.io/journey-planner/v3/graphql" \
-H "Content-Type: application/json" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" \
-d '{"query": "{ stopPlace(id: \"NSR:StopPlace:59872\") { name estimatedCalls(numberOfDepartures: 10) { expectedDepartureTime destinationDisplay { frontText } serviceJourney { journeyPattern { line { publicCode name transportMode } } } } } }"}' | jq '.data.stopPlace | {name: .name, departures: [.estimatedCalls[] | {time: .expectedDepartureTime, destination: .destinationDisplay.frontText, line: .serviceJourney.journeyPattern.line.publicCode, mode: .serviceJourney.journeyPattern.line.transportMode}]}'
注意事项
- GraphQL API。仅支持 POST。唯一的端点:
https://api.entur.io/journey-planner/v3/graphql - 所有请求都要设置
ET-Client-Name标头。 - 没有速率限制密钥,但请合理使用。
- Schema 浏览器:https://api.entur.io/graphql-explorer/journey-planner-v3
- 通过 Vy 和 SJ Nord 覆盖部分通往瑞典的跨境线路。
瑞典:ResRobot v2.1
Trafiklab 提供的 REST API。覆盖瑞典所有公共交通:SJ 火车、区域巴士、渡轮、地铁、通勤铁路。
身份验证
在 .env 中设置 RESROBOT_API_KEY。使用 accessId 查询参数。可在 trafiklab.se 免费获取密钥。每月 30,000 次调用。
行程搜索(斯德哥尔摩至哥德堡)
curl -s "https://api.resrobot.se/v2.1/trip?originId=740000001&destId=740000002&format=json&accessId=$RESROBOT_API_KEY" | jq '[.Trip[] | {start: .LegList.Leg[0].Origin.time, date: .LegList.Leg[0].Origin.date, duration: .duration, legs: [.LegList.Leg[] | {mode: .type, name: .name, from: .Origin.name, to: .Destination.name, depart: .Origin.time, arrive: .Destination.time}]}] | .[0:5]'
查找站点 ID
curl -s "https://api.resrobot.se/v2.1/location.name?input=Stockholm&format=json&accessId=$RESROBOT_API_KEY" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId}] | .[0:5]'
主要站点 ID
| 城市 | 站点 ID | 名称 |
|---|---|---|
| Stockholm C | 740000001 | Stockholm Centralstation |
| Gothenburg C | 740000002 | Goteborg Centralstation |
| Malmo C | 740000003 | Malmo Centralstation |
| Uppsala | 740000025 | Uppsala Centralstation |
| Linkoping | 740000009 | Linkoping Centralstation |
行程参数
| 参数 | 必填 | 说明 |
|---|---|---|
originId | 是 | 出发站点 ID |
destId | 是 | 到达站点 ID |
date | 否 | YYYY-MM-DD(默认今天) |
time | 否 | HH:MM(默认当前时间) |
format | 否 | json 或 xml |
numTrips | 否 | 结果数量(默认 5) |
products | 否 | 交通类型位掩码 |
注意事项
- REST API。基址:
https://api.resrobot.se/v2.1/ - 包含开往哥本哈根的跨境厄勒海峡列车。
- 不提供票价数据。仅包含时刻表和路线。
丹麦:Rejseplanen API 2.0
REST API(HAFAS v2.50.4.1)。覆盖丹麦所有公共交通:DSB InterCity/InterCityLyn、S-Tog、地铁、区域列车、巴士、快速巴士、夜班巴士、渡轮、Flextur。独特之处:包含票价和区域票价数据。
文档:https://labs.rejseplanen.dk(需要登录)。XSD 架构:https://www.rejseplanen.dk/api/xsd
身份验证
在 .env 中设置 REJSEPLANEN_API_KEY。作为 accessId 查询参数传递。在 labs.rejseplanen.dk 申请。每月免费调用 50,000 次(非商业用途)。
常用参数
| 参数 | 说明 |
|---|---|
accessId | 必填。 API 密钥。 |
format | json 或 xml。始终使用 format=json。 |
lang | 默认值为 da。使用 lang=en 获取英文。 |
产品位掩码
| Value | Product | Description |
|---|---|---|
| 1 | IC | 城际列车 |
| 2 | ICL | InterCityLyn(特快) |
| 4 | Re | 区域列车 |
| 8 | Other | ECE、Eurostar、RailJet、Togbus、DSB Udland |
| 16 | S-Tog | 哥本哈根通勤铁路 |
| 32 | Bus | 本地巴士 |
| 64 | ExpressBus | 特快巴士(250S、X-bus) |
| 128 | NightBus | 夜间巴士 |
| 256 | Flextur | 响应式交通 |
| 1024 | Metro | 哥本哈根地铁 |
仅列车 = products=31。全部公共交通 = 省略参数。
主要站点 ID
| Stop | extId | Name |
|---|---|---|
| København H | 8600626 | København H |
| CPH Lufthavn | 8600858 | CPH Lufthavn |
| Odense St. | 8600512 | Odense St. |
| Aarhus H | 8600053 | Aarhus H |
| Aalborg St. | 8600020 | Aalborg St. |
| Svendborg St. | 8600551 | Svendborg St. |
| Svendborg Færgehavn | 100200261 | Svendborg Færgehavn |
| Ærøskøbing Havn (færge) | 100200222 | Ærøskøbing Havn (færge) |
位置端点
location.name(按名称搜索)
curl -s "https://www.rejseplanen.dk/api/location.name?accessId=$REJSEPLANEN_API_KEY&input=København&format=json&type=S" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId, lat: .lat, lon: .lon}] | .[0:10]'
| Param | Required | Description |
|---|---|---|
input | 是 | 搜索查询 |
type | 否 | S(站点)、A(地址)、P(兴趣点),或组合使用 |
maxNo | 否 | 最大结果数(默认 10,最大 1000) |
products | 否 | 产品位掩码筛选条件 |
r, refCoordLat, refCoordLong | 否 | 半径和参考坐标,用于距离排序 |
location.nearbystops(坐标附近的站点)
curl -s "https://www.rejseplanen.dk/api/location.nearbystops?accessId=$REJSEPLANEN_API_KEY&originCoordLat=55.672793&originCoordLong=12.564590&r=500&format=json" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId, dist: .dist}] | .[0:10]'
需要 originCoordLat/originCoordLong。可选参数:r(半径,默认 1000m)、maxNo、type、products。
location.details
根据完整 HAFAS ID 查询单个位置的详情(URL 编码)。
location.data
查询数值 ID 范围内的地点(llId 至 urId)。
location.search
筛选位置搜索。参数与 location.name 相同,并支持其他筛选条件。
location.boundingbox
查询地理范围框内的所有站点(llLat/llLon 至 urLat/urLon)。
addresslookup
查询坐标附近的地址。反向地理编码。需要 originCoordLat/originCoordLong。
行程规划端点
trip(路线规划)
curl -s "https://www.rejseplanen.dk/api/trip?accessId=$REJSEPLANEN_API_KEY&originId=8600626&destId=8600551&date=2026-08-28&time=08:00&format=json&lang=en" | jq '[.TripList.Trip[] | {duration: .duration, legs: [.LegList.Leg[] | {name: .name, type: .type, from: .Origin.name, to: .Destination.name, depTime: .Origin.time, arrTime: .Destination.time, track: .Origin.track}]}] | .[0:3]'
| Param | Required | Description |
|---|---|---|
originId | 是* | 出发站点 extId |
destId | 是* | 目的地站点 extId |
originCoordLat/Long | 是* | 按坐标指定出发地(替代 originId) |
destCoordLat/Long | 是* | 按坐标指定目的地(替代 destId) |
date | 否 | YYYY-MM-DD |
time | 否 | HH:MM |
searchForArrival | 否 | 1 = 按到达时间搜索 |
numF | 否 | 向前查询的结果数(1-6) |
numB | 否 | 向后查询的结果数(0-3) |
maxChange | 否 | 最大换乘次数(0-11) |
products | 否 | 产品位掩码 |
operators | 否 | 以逗号分隔的运营商代码 |
lines | 否 | 线路筛选条件 |
via | 否 | 经停站点 ID |
avoid | 否 | 避开的站点 ID |
passlist | 否 | 1 = 包含中间站点 |
tariff | 否 | 1 = 包含票价/区域定价 |
poly | 否 | 1 = 包含折线 |
context | 否 | 用于分页的滚动令牌 |
originWalk/Bike/Car | 否 | 接驳方式距离 |
destWalk/Bike/Car | 否 | 离站方式距离 |
rtMode | 否 | FULL、INFOS、OFF、REALTIME、SERVER_DEFAULT |
interval(时间段行程搜索)
查询时间范围内的所有出发班次。参数与 trip 相同。
recon(行程重建)
根据 ctxRecon 令牌重建行程。参数:ctx(必需)、poly、passlist、tariff。
reachability(所有可达站点)
查询在时间/换乘次数限制内可到达的所有站点。参数:originId 或坐标、duration(1-1439 分钟)、maxChange(0-11)、forward、products。
出发和到达信息板
默认时长:60 分钟。
departureBoard / arrivalBoard
curl -s "https://www.rejseplanen.dk/api/departureBoard?accessId=$REJSEPLANEN_API_KEY&id=8600626&date=2026-08-28&time=08:00&format=json&lang=en" | jq '[.DepartureBoard.Departure[] | {name: .name, time: .time, direction: .direction, track: .track, rtTime: .rtTime}] | .[0:10]'
参数:id(必需)、date、time、duration(0-1439)、maxJourneys、products、operators、passlist。
multiDepartureBoard / multiArrivalBoard
在一次调用中查询多个站点。传入多个 id 参数。
nearbyDepartureBoard / nearbyArrivalBoard
坐标附近的车站。参数:originCoordLat/Long、r(默认 1000m)、maxStops(默认 30)。
线路和行程端点
lineinfo
指定日期的线路详情。需要 lineId、date。
linesched
指定日期的线路完整时刻表。需要 lineId、date。
linesearch
按运营商搜索所有线路。需要 operators(逗号分隔,来自 datainfo)。
linematch
按模式字符串匹配线路。
trainSearch
按列车名称查找行程。仅返回首末站。
journeyDetail
行程的完整停靠站列表。需要 id(来自行程/站台的行程引用)。可选:fromId/toId、poly、rtMode。
journeyMatch
类似 trainSearch,但仅返回首个匹配项的完整详情。
journeypos
边界框内的实时车辆位置。需要 llLat/llLon/urLat/urLon。
票价 / 定价端点
丹麦通过 Rejsekort 实行基于区域的定价,在斯堪的纳维亚独具特色。
| 端点 | 用途 |
|---|---|
trip with tariff=1 | 在行程结果中内嵌票价 |
spPrice | 按出发地/目的地查询季票价格 |
spPriceForZones | 查询票价集内指定区域数量的每日价格 |
spDailyZonalPrices | 完整的区域价格矩阵,涵盖所有乘客类型 |
spPriceReconstruction | 根据行程重建上下文查询价格 |
spRefund | 计算季票退款 |
spCheck | 验证季票(SELF 系统) |
spZoneCheck | 检查区域连通性和地铁区域 |
stRoutes | 查询出发地/目的地之间的票价路线 |
stRoutesAddon | 查询单一起点出发的票价路线 |
stStops | 查询票价区域和站点(mode=DSB) |
trfStop | 查询某区域的默认站点 |
convertZones | 查询上下文的票价详情 |
zoneFromCoordinate | 按纬度/经度查询区域 |
出行详情端点
gisroute
行程结果中的步行/骑行路线详情。需要 ctx(GIS 引用)。
himsearch
实时交通中断消息。可按交通产品、运营商、线路、日期和站点筛选。
系统信息
datainfo
所有运营商、交通产品和类别。用于查找运营商代码。
curl -s "https://www.rejseplanen.dk/api/datainfo?accessId=$REJSEPLANEN_API_KEY&format=json" | jq '[.DataInfo.operators.Operator[] | {name: .name, id: .id}] | .[0:20]'
tti
时刻表数据池信息:ID、创建日期、类型(ST/ADR/POI)、有效期。
响应结构
extId:数字站点 ID(用于查询)。id是完整的 HAFAS 字符串。rtTime/rtDate:实时实际/预测时间(与计划的time/date不同时)。- 区段
type:JNY(行程)、WALK(步行)、TRSF(换乘)。 JourneyDetailRef:与journeyDetail搭配使用,以获取完整停靠站列表。
跨境路线
| 路线 | 覆盖范围 | 备注 |
|---|---|---|
| 奥斯陆至斯德哥尔摩 | Entur + ResRobot | SJ 列车,约 6 小时 |
| 马尔默至哥本哈根 | ResRobot + Rejseplanen | 厄勒海峡列车,35 分钟 |
| 哥德堡至奥斯陆 | Entur + ResRobot | Vy/SJ,约 4 小时 |
| 斯德哥尔摩至哥本哈根 | ResRobot | SJ/DSB,经马尔默约 5 小时 |
| 哥本哈根至马尔默 | Rejseplanen | 从丹麦一侧出发的厄勒海峡列车 |
适用场景
在以下情况下加载此技能:
- 规划斯堪的纳维亚城市之间的火车/公交/渡轮路线
- 查询地面交通的时刻表和耗时
- 查找行程规划所需的站点 ID
- 比较斯堪的纳维亚境内路段的火车与航班
- 查询丹麦公共交通票价/区域
- 查询实时交通中断情况(
himsearch) - 跟踪实时车辆位置(
journeypos)
请勿:
- 用于预订(仅支持搜索/时刻表查询)
- 用于航班(请使用 Seats.aero、SerpAPI 或 Duffel)
- 期待从 Entur 或 ResRobot 获取票价(只有 Rejseplanen 提供票价)
搜索工作流
1. “如何从 A 到达 B?”
步骤 1: 按国家选择 API(挪威=Entur,瑞典=ResRobot,丹麦=Rejseplanen,跨境=两者)。
步骤 2: 查找站点 ID:
# Norway
curl -s "https://api.entur.io/geocoder/v1/autocomplete?text=Flåm&size=3" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" | jq '[.features[] | {name: .properties.name, id: .properties.id}]'
# Sweden
curl -s "https://api.resrobot.se/v2.1/location.name?input=Malmö&format=json&accessId=$RESROBOT_API_KEY" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId}] | .[0:5]'
# Denmark
curl -s "https://www.rejseplanen.dk/api/location.name?accessId=$REJSEPLANEN_API_KEY&input=Svendborg&format=json&type=S&lang=en" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId}] | .[0:5]'
步骤 3: 使用 date 和 time 搜索行程。步骤 4(丹麦): 添加 tariff=1 查询票价。
2. “从 X 出发的列车有哪些?”
curl -s "https://www.rejseplanen.dk/api/departureBoard?accessId=$REJSEPLANEN_API_KEY&id=8600626&duration=120&products=31&format=json&lang=en" | jq '[.DepartureBoard.Departure[] | {time: .time, name: .name, direction: .direction, track: .track}]'
3. “我附近有什么?”
curl -s "https://www.rejseplanen.dk/api/location.nearbystops?accessId=$REJSEPLANEN_API_KEY&originCoordLat=55.6736&originCoordLong=12.5681&r=500&format=json&lang=en" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId, dist: .dist}]'
或者使用 nearbyDepartureBoard 跳过站点查询。
4. “去 Ærø 坐什么渡轮?”
curl -s "https://www.rejseplanen.dk/api/trip?accessId=$REJSEPLANEN_API_KEY&originId=100200261&destId=100200222&date=2026-08-28&time=08:00&format=json&lang=en" | jq '[.TripList.Trip[] | {legs: [.LegList.Leg[] | {name: .name, from: .Origin.name, to: .Destination.name, depTime: .Origin.time, arrTime: .Destination.time}]}] | .[0:5]'
5. “我知道列车号。”
使用 trainSearch 查找列车,然后将 ref 传给 journeyDetail 以获取完整停靠站信息。
6. “两小时内我能到哪里?”
curl -s "https://www.rejseplanen.dk/api/reachability?accessId=$REJSEPLANEN_API_KEY&originId=8600626&duration=120&maxChange=2&format=json" | jq '.'
7. “有中断或延误吗?”
curl -s "https://www.rejseplanen.dk/api/himsearch?accessId=$REJSEPLANEN_API_KEY&format=json&lang=en" | jq '.'
8. 跨国行程
从两端分别搜索。Øresund 列车会同时出现在 ResRobot 和 Rejseplanen 中。
提示
- 始终使用
format=json。对于 Rejseplanen,始终使用lang=en。 - 查询时使用数值型
extId,不要使用较长的 HAFASid字符串。 - 检查
rtTime/rtDate以查看延误。 passlist=1可显示中途站点。maxChange=0仅显示直达路线。- 使用
numF/numB或context翻页令牌进行分页。 - 产品位掩码采用累加方式。不指定则包含所有类型。