昨天預告過了:今天來講 YouBike 查詢怎麼從雙北長到四個城市。本來以為是「多接兩個 API」的小事,結果變成這次升級裡踩最多坑的一個——而且坑踩完之後,隔天又來了一個大反轉。
YouBike 2.0 的站點即時資料,理論上各縣市政府都會透過開放資料平台釋出。所以擴充計畫聽起來很簡單:找到各縣市的 feed,寫進 SKILL.md,收工。
實際上每個城市各自為政。收錄的四個來源長這樣(實測日期:2026-09-09):
| 城市 | 來源 | 站數 |
|---|---|---|
| 台北市 | tcgbusfs.blob.core.windows.net | 約 1,800 站 |
| 新北市 | data.ntpc.gov.tw JSON API | 約 1,600 站 |
| 台中市 | newdatacenter.taichung.gov.tw | 約 1,800 站 |
| 桃園市 | opendata.tycg.gov.tw | 約 700 站 |
同一個 YouBike,四套 endpoint、四套欄位命名。台北用 available_rent_bikes,新北用 sbi_quantity,台中和桃園用 sbi。回傳型別也不統一:台北給數字,其他三市給字串。連更新時間格式都有三種:台北是 "YYYY-MM-DD HH:MM:SS",新北是 "YYYYMMDDTHHMMSS",台中和桃園是 "YYYYMMDDHHMMSS"。這些差異最後全部整理成對照表放進 SKILL.md,查詢的人(或 AI)不用每個城市重新猜一次。
接桃園的時候,curl 回來的 JSON 我數了一下:20 站。桃園好歹一百多萬人,YouBike 只有 20 站?怎麼想都不對。
仔細看才發現,桃園的 API 預設只回 20 筆,要加上 limit 參數才會給全量:
curl -s "https://opendata.tycg.gov.tw/api/v1/dataset.api_access?rid=08274d61-edbe-419d-8fcc-7a643831283d&format=json&limit=2000"
帶了 limit=2000 之後,七百多站整整齊齊地出現。如果當初只看回傳「有資料」就收工,這個 skill 就會永遠以為桃園只有 20 站。這也是為什麼 repo 的鐵則是「實測過才收錄」:不只要確認打得通,還要確認數量合理。
電輔車(YouBike 2.0E)篩選是這次的重點之一。新北很佛心,直接給 eyb_quantity 欄位。台中和桃園就把電輔車數量塞在一個叫 sbi_detail 的欄位裡,而且兩市格式還不一樣:台中是逗號分隔字串("5,1"=一般車 5、電輔車 1),桃園是 JSON 字串({"yb2":5,"eyb":1}),要再 parse 一次。
台中那個 "5,1" 的順序,官方文件沒寫清楚。我的驗證方式很土法煉鋼:找一個 sbi(總可借)等於 6 的站,它的 sbi_detail 是 "5,1",5+1=6 對得起來,再挑幾個站交叉比對才確認順序。文件沒寫的東西,就用資料自己證明。
你以為欄位對齊就沒事了?站名還有「台」跟「臺」的問題。台北市的資料裡,一百多個站用「臺」,其他用「台」;新北也混著用。使用者打「台大」搜尋,結果站名是「臺大」,就直接查無此站。最後在查詢範例裡加了正規化指引:搜尋前先把「臺」換成「台」(jq 的 gsub("臺";"台")),或兩個寫法都試。
還有台北和新北的邊界問題:很多站蓋在兩市交界,住永和的人最近的站可能在台北市的 feed 裡。所以查「附近站點」時,兩個城市的資料要合起來算距離,不能各查各的。
四個城市接完,我本來已經接受「YouBike 資料就是碎的」這個事實。結果隔天整理程式碼的時候發現:YouBike 官方網站自己用的一支 JSON,一次給全台灣的即時資料:
https://apis.youbike.com.tw/json/station-yb2.json
14 個縣市、九千五百多個站,欄位統一:available_spaces、empty_spaces、status,連 available_spaces_detail 都直接拆好 {"yb1","yb2","eyb"}。昨天還在頭痛的電輔車篩選,這支 feed 直接內建。
但這裡要冷靜:這支 feed 是 YouBike 公司網站自己用的,不是政府開放資料平台,沒有正式文件,隨時可能改格式或關掉。所以最後的架構是雙軌:查全台(包含昨天忍痛放棄的高雄)用這支統一 feed,各縣市的政府開放資料當備援。repo 的規矩沒變——沒驗證過的不收,驗證過的也要講清楚它的風險。
順帶一提,台北市政府的 feed 裡沒有電輔車欄位,所以「台北市+電輔車」這個組合,以前只能說不支援,現在可以導到統一 feed 查。
功能接完,回頭把文件和 CI 也補強了一輪:站數從硬寫的數字改成「約幾站+實測日期」(桃園一天之內就從 702 漂到 703),health-check 腳本除了看 HTTP status,還開始解析回傳的 JSON、檢查站數有沒有低於門檻(專抓「HTTP 200 但其實是錯誤頁」的沉默失敗),CHANGELOG 記上每一筆改動的理由。
youbike-realtime 從「雙北限定」長成「全台 14 縣市」:統一 feed 當主力、四市政府開放資料當備援、電輔車可單獨篩選、暫停營運的站如實回報、台臺異體字有解。昨天寫「高雄忍痛排除」的我,今天被一支 JSON 拯救了。
明天換垃圾車出場:taipei-garbage 是怎麼改名成 taiwan-garbage 的,新北市的兩萬六千多筆清運點又是怎麼分頁抓完的。