請啟用JavaScript來查看內容

「PTX 公共運輸資訊平台」API 介紹 (含 Odata 說明)

·

    因部內目前已收攏資料於TDX運輸資訊整合流通服務平台,本平台預計將於2022/12/1落日,屆時您的會員金鑰將於2022/12/1起停用。
    為避免您短時間內需移轉之困擾,即日起本平台不再受理審核會員註冊。
    建議您依據身分類型至TDX申請會員,非常感謝您的支持。

    前言

    你手機裡很可能有安裝臺鐵、高鐵、捷運、公車等等公共運輸的 APP,或者使用過查詢時刻表、動態相關網站(示範應用列表),但他們是怎麼取得這些資料的呢?

    原來有個政府的平台 — 公共運輸整合資訊流通服務平台,它整合並提供這些數據資料,以 Web API 的形式提供我們串接。


    關於 PTX 平台我寫了三篇文章來介紹與程式教學:

    1. 「PTX 公共運輸資訊平台」API 介紹 (含 Odata 說明) <– 本篇
    2. 「PTX 公共運輸資訊平台」Python 範例
    3. 「PTX 公共運輸資訊平台」Google Apps Script 範例

    PTX 公共運輸整合資訊流通服務平台
    PTX 公共運輸整合資訊流通服務平台

    後來發現 PTX 竟然只服務到今年(2022年)底,之後會改以 TDX 運輸資訊整合流通服務平台,因此又特別寫一篇文章帶大家快速了解一下 TDX 平台:
    「TDX 運輸資料流通服務平臺」含 Python 範例程式,PTX 平台的升級版~


    PTX 簡介

    為了推動公共運輸整合資訊開放 (Open Data) 、統整各機關(構)的多元公共運輸資訊,交通部推出了這個 PTX 平台,包含了臺灣的公車、臺鐵、高鐵、捷運、航空、自行車、航運(海運)、觀光景點等公共運輸資料服務 API,非常的多樣,幾乎在臺灣你想的到的大眾交通工具都包在裡頭。
    像是:臺鐵票價資料、高雄輕軌時刻表、臺北捷運即時通阻事件、機場即時入境航班、公車即時位置、公共自行車剩餘數量、觀光景點……等等。

    PTX 網站有個「各項服務查詢」供檢視平台提供的服務,能依照 "領域類型"、"資料類型"、"業管機關" 去做篩選,每個服務還可以快速點開 API 說明及網址範例,另外還有整理成表格顯示:目前各單位資料供應現況表

    PTX 各項服務查詢
    PTX 各項服務查詢

    加入會員 & 取得 APP ID 與 APP Key

    為了提供穩定的服務、加強資訊安全管理,要使用此平台的 API 前需要先加入會員。

    加入會員

    進入 加入會員 頁面,在此選擇「一般會員」即可,「進階會員」、「專案用戶」有更多的呼叫次數及其他權益,但那還要提供額外的證明,一般會員的 API 呼叫次數上限 20,000 次/日已經很夠我們自己玩玩,或做個小應用了。
    (因為我以前註冊過,這邊就不演示了,按照網頁流程操作應該不會有什麼問題。)

    申請加入 PTX 會員
    申請加入 PTX 會員

    取得 APP ID 與 APP Key

    (APP ID 與 APP Key 下一篇文章使用 Python 實際操作時才會用到)

    註冊完成並等待三個工作日審核後,會收到一封 Email,之後我們會使用到「基礎資料服務(L1)」的「APP ID」與「APP Key」。
    而目前提供的資料服務多屬 L1,L2 的服務目前僅有場站空氣品質服務 (不知道現在 L2 是否有加入其他的服務)。


    或者也可登入後到 API金鑰申請 取得,如果忘記 APP Key 可點擊「忘記APP Key」即可,但要注意舊的 APP Key 就會失效,所以如果你 APP Key 不小心公開了也可由此來重新產生,避免額度被其他人使用。

    取得 APP ID 與 APP Key
    取得 APP ID 與 APP Key

    API 說明

    可以參考官方提供的「資料使用葵花寶典」,此手冊分成以下四點作介紹說明

    • API 會員:各會員層級進行說明並提供會員申請流程。
    • API 使用說明:API 呼叫方法及注意事項進行說明。
    • API 特色說明:API 獨特的使用技巧進行說明。
    • API 資料使用注意事項:各運具資料面注意事項進行說明。

    PTX 的 API 是以 OData(Open Data Protocol)標準介面格式對外開放供使用。


    URI 設計概念

    先來看看 URI 的設計概念。

    這邊以臺鐵 "取得指定[日期],[車站]的站別時刻表資料" 為例:

    臺鐵 "取得指定[日期],[車站]的站別時刻表資料"
    臺鐵 "取得指定[日期],[車站]的站別時刻表資料"

    從這張圖可以清楚的看出來,最前方 "基本網址" 大家都一樣,再來是 "API版本"、"鐵道" 中的 "臺鐵",我們想抓的 "站別時刻表",以及最後方帶入的參數 "車站代碼" 與 "日期"。
    (車站代碼可以從另外一個 "車站基本資料" API 取得,或臺鐵官網的車站代碼表)

    雖然每項服務會有些不同,但其網址結構都是差不多的,這邊稍微知道就好,詳細說明請參考官方提供的「API URI Convention文件」。


    Swagger 文件工具

    至於各項服務 API 說明可以從這裡進入,或到「PTX 各項服務查詢」點擊對應服務右方的"服務說明",它是透過 Swagger 這個文件工具來呈現。


    這邊先講個 Swagger 基本使用。

    找一個感興趣的資源(Resource),並打開其 API 說明。

    API 介面說明
    API 說明

    大致分為幾個部分,最上方針對此資源簡短描述,再來 "Parameters" 是此資源可附加上的參數,像是我想看哪一個捷運系統的車站資料,就是在這邊帶上參數,除了標示 required 紅字為必填,其餘我們先暫時不必理會。最後 "Responses" 會寫到當回應哪個 HTTP Status Code 對應是哪個意思,其回應資料格式又是長什麼樣子。

    API 介面說明
    API 說明

    回應資料有些欄位可能看不出它代表意思,就可以到這邊找找說明。

    API 介面說明
    API 說明

    在 Parameters 與 Responses 中間有個大大的藍色 "Execute" 按鈕,我們給他用力按下去。

    噹🌟!發現在底下 "Responses" 區塊跑出好幾個新東西:

    • "Request URL" 代表依照你上方設定的參數,其請求網址會長怎樣。
    • "Server response" 顯示回應 HTTP Status Code 及回應內容(Response body),回應內容就是我們想要的資料啦~
    API 回應說明
    API 回應說明

    這個 Swagger 工具大致上的用法就是這樣。


    到這邊,都可以如實拿到想要的資料了。

    但可能它每次回傳的資料量很大,我只是需要其中的一部分資料而已,這樣會浪費頻寬、增加回應時間、接收到資料後還要費力處理,那有沒有能在送出請求時,就告訴 Server 我們想要那些資料呢?
    有的!!接下來就要講到 Odata 這個介面格式厲害的地方了😮


    Odata 查詢語法

    通過 Odata 協定制定的用法,我們可以去做多樣的查詢、過濾、排序,甚至有更進階的函數語法。

    我會依序介紹以下六種 Odata 的查詢方法:

    • $format 指定來源格式
    • $orderby 排序
    • $top 取前幾筆
    • $skip 跳過前幾筆
    • $select 挑選
    • $filter 過濾

    這邊我是依照比較好理解的順序介紹說明,最後再舉幾個複合範例給各位參考。


    $format 指定來源格式

    指定回傳資料要以什麼格式。

    PTX 提供 JSON 與 XML 兩種格式供選擇。

    • $format=json
    • $format=xml

    $orderby 排序

    指定回傳資料的排序。

    升冪:由小到大;降冪:由大到小。

    • 針對欄位1作升冪 (預設)
      $orderby=Field1
      $orderby=Field1 asc
    • 針對欄位1作降冪
      $orderby=Field1 desc
    • 針對欄位1作升冪,欄位2降冪
      $orderby=Field1 asc,Field2 desc

    各 API 服務有不同的回傳資料,例如我在查詢公共自行車即時車位時,希望資料依照 "可租借數量" 由多至少排列:
    $orderby=AvailableRentBikes desc

    $top $skip 取前幾筆

    這兩個是類似的概念。

    • $top:取前幾筆資料。
    • $skip 跳過前幾筆資料。

    像是我想拿取前 11~30 筆資料:
    $top=20&$skip=10

    $select 挑選

    指定只需要回傳那些欄位,多個欄位可用逗號(,)隔開,未指定則回傳全部欄位。
    (目前只支援第一層欄位)

    • 只回傳欄位1
      $select=Field1
    • 回傳多個欄位,欄位1和欄位2
      $select=Field1,Field2

    不過它有但書:

    • 回傳資料指定為 json 時,只會回傳被 select 的欄位,除此之外,若其他欄位為非 nullable,也會回傳系統預設值。
    • 回傳資料指定為 xml,沒有被指定的屬性若為 class 或是 string,不會回傳該欄位,但若是其他屬性(int,bool,enum..),還是會回傳該欄位,其值為系統預設值。

    $filter 過濾

    (來到最複雜、最多變化的一個語法了😅)

    filter 語法是用來對資料做篩選、過濾,提供「邏輯運算子」、「算術運算子」、「規範函數」、「Lambda Operators」可使用。


    邏輯運算子 (Logical Operators)

    邏輯運算子意義
    eq等於
    ne不等於
    gt大於
    ge大於等於
    lt小於
    le小於等於
    and而且、和
    or或者
    not否定
    • 例如想查詢公共自行車 "可租借數量" 大於 10 台的站點:
      $filter=AvailableRentBikes gt 10

    • 假如欄位是在第二層,則可透過 / 連接。
      例如想取得高雄捷運 "左營站 " 的即時到離站電子看板:
      $filter=StationName/Zh_tw eq '左營'

    * 要注意後方比對的字串需使用單引號 ' 框起來,雙引號 " 是不行的哦。


    算術運算子 (Arithmetic Operators)

    算數運算子意義
    add
    sub
    mul
    div
    mod餘數
    • 例如我想查詢有哪台公車目前時速是奇數:
      $filter=Speed mod 2 eq 1
      (知道這個好像也不能幹嘛……)

    規範函數 (Canonical Functions)

    規範函數意義規範函數意義
    substring子字串year年份
    startswith字串開頭month月份
    endswith字串結尾day
    length字串長度hour小時
    indexof指定字串出現位置minute
    tolower字串變小寫second
    toupper字串變大寫fractionalseconds小數秒
    trim去空白date日期
    contains包含time時間
    concat串接
    round四捨五入
    floor無條件捨去
    ceiling無條件進位
    cast轉型
    • 例如取得公車動態中車牌號碼開頭是 "001" 的資料:
      $filter=startswith(PlateNumb, '001')

    • 或者想知道車牌號碼長度為 7 個字的公車:
      $filter=length(PlateNumb) eq 7

    • 去台南旅遊,想找出店名包含 "豆花" 的店家:
      $filter=contains(RestaurantName,'豆花')


    Lambda Operators

    Lambda Operators意義
    all所有項目都要符合
    any其中一項符合
    • 例如我想知道今天有哪幾班高鐵會停 "雲林":
      $filter=StopTimes/any(d:d/StationName/Zh_tw eq '雲林')

    這部分可能一開始有些難懂,主要是用在判斷陣列中的值。
    * 其中的 d 是可以隨意換其他名稱的。



    多種複合用法

    為了讓大家更容易理解,這邊我再舉幾個多種語法所組合的用法:

    • 想看看高鐵在今年(2022年) 3 月之後有發布什麼關於 "左營" 的最新消息:
      $filter=year(PublishTime) eq 2022 and month(PublishTime) ge 3 and contains(Title,'左營')
      (啊…4/1 水泥施工事故導致電力異常,台南-左營站間停駛)

    • 台南市公車中,路線是 "紅" 字開頭,並且目前 "時速超過 30 公里",依照時速由大排到小的前五名:
      $filter=startswith(SubRouteName/Zh_tw,'紅') and Speed gt 30&$orderby=Speed desc&$top=5

    • 因為提著大包小包,想知道台北捷運 "古亭站" 有哪個出口有 "電扶梯" 或 "電梯",且只回傳 "出口" 和 "地址":
      (備註:Escalator 是否有電扶梯(0:沒有,1:雙向,2:出站,3:入站))
      $select=ExitName,LocationDescription&$filter=StationName/Zh_tw eq '古亭' and (Escalator ne 0 or Elevator eq true)



    有關如何使用 Odata 查詢 PTX API 資料,官方有整裡個簡報—「PTX APIs開發技術說明(含Odata)」,裡頭有更詳細地介紹 Odata,以及其查詢選項、函數語法。

    當然,如果你覺得這些篩選語法太麻煩,也是可以全部抓下來後,再使用程式去處理。


    API 呼叫統計

    PTX 平台也提供「服務呼叫統計」網頁,可查看自己目前的資料數據傳輸量、呼叫次數以及虛擬點數等等統計數據,確認還有多少額度可以使用,甚至也針對各項服務做統計。

    PTX 服務呼叫統計
    PTX 服務呼叫統計
    PTX 服務呼叫統計
    PTX 服務呼叫統計

    結語

    有了這個 PTX 平台後,想要取得各大眾公共運輸的資料變得相當容易,除了做成應用程式自用外,也可以公開讓大家使用。

    官方也有整理一些 常見問題 供參考。


    如何?看完介紹後你腦中是否產生有趣的 idea 了呢😙
    別急,下一篇文章會來教你該如何使用 Python 來串接 PTX API,以及需要注意什麼事情。


    歡迎追蹤『IT空間』FB 粉專,取得最新發文通知🔔




    參考:
    公共運輸整合資訊流通服務平台 | 官網
    PTX 資料使用葵花寶典
    PTX API 說明 | Swagger
    PTX APIs開發技術說明(含Odata)


    等待奇蹟,不如為自己留下努力的軌跡;期待運氣,不如堅持自己的勇氣。

    —— 李洋 (台灣羽球國手)


    🔻 如果覺得喜歡,歡迎在下方獎勵我 5 個讚~
    分享

    Jia
    作者
    Jia
    軟體工程師