請啟用 JavaScript 來查看內容

「PTX 公共運輸資訊平台」Google Apps Script 範例程式

·

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

    前言

    在之前的兩篇文章裡,我們分別介紹 PTX 公共運輸整合資訊流通服務平台 整合多項大眾運輸的資料、說明 OData(Open Data Protocol)格式如何使用,與實際使用 Python 來串接 PTX 平台。

    本篇文章將帶你換成使用 Google Apps Script 來串接 PTX 平台,取得這些相關數據資料 💾,還可以做出自己的簡易 API。
    (Google Apps Script 其實是基於 JavaScript 來的,所以基本的語法大致都相同。)


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

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

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

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


    創建 Google Apps Script 專案

    可能有些人沒接觸過 Google Apps Script,我這邊先說明兩種創建的方式:

    第一種到 Apps Script 頁面 創建專案,預設會儲存在你 Google 雲端硬碟的根目錄。

    創建 Google Apps Script 專案 -1
    創建 Google Apps Script 專案 -1

    第二種在 Google 雲端硬碟裡新增 Google Apps Script 檔案 (如果選單內沒看到,可以點擊 "連結更多應用程式" 去尋找&加入)。

    創建 Google Apps Script 專案 -2
    創建 Google Apps Script 專案 -2

    選擇一種你順手的方式創建專案即可,好了我們就開始吧 🚌


    API 認證授權機制

    一樣先撰寫放在 Header 裡的 HMAC 認證授權 🔓,關於目前 PTX 平台採用 HMAC 認證授權機制說明,可以參考上一篇文章

    參數如下:

    KeyValue
    Authorizationhmac username="APP ID", algorithm="hmac-sha1", headers="x-date", signature="Base64(HMAC-SHA1("x-date: " + x-date , APP Key))"
    x-dateWed, 19 Apr 2017 08:37:50 GMT

    ※ 建議於每次請求 API 服務當下建立新的 signature,簽章時效性為 5 分鐘。


    如果 HMAC 認證有問題、未符合身份驗證,它會回覆下列訊息:

    • HTTP Status Code 403:
      • (1) HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication (x-date 的間隔時間超過定義的 clock skew 秒數)
      • (2) HMAC signature does not match (日期格式正確,但簽章演算法有問題)
    • HTTP Status Code 401:
      • (1) Unauthorized (未帶簽章,未經授權)


    依照上方說明,使用 Google Apps Script 語法把這個 HMAC 編碼撰寫出來:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    function GetAuthorizationHeader() {
      var AppID = '<YOUR APP ID>';
      var AppKey = '<YOUR APP KEY>';
      var xdate = new Date().toGMTString();
      //HMAC-SHA1 運算
      var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1, "x-date: " + xdate, AppKey);
      //轉成Base64
      var HMAC = Utilities.base64Encode(signature);
      var Authorization = 'hmac username=\"' + AppID + '\", algorithm=\"hmac-sha1\", headers=\"x-date\", signature=\"' + HMAC + '\"';
      return { 'Authorization': Authorization, 'x-date': xdate ,'Accept-Encoding': 'gzip'};
    }
    

    Google Apps Script 程式範例

    我們一樣使用上次的例子:

    台鐵"台北"車站即時的列車到離站看板資訊,並且只要"逆行"的列車


    先進到 PTX 平台的 Swagger 文件,找到 "取得指定[車站]列車即時到離站電子看板":

    列車即時到離站電子看板
    列車即時到離站電子看板

    填入 "台北車站" 代碼 1000 (車站代碼表),並依照下方 Responses 欄位說明 "Direction" 代表順逆行(0:'順行', 1:'逆行'),在 $filter 填入 Direction eq 1,指定 JSON 格式,最後點擊藍色 "Execute" 按鈕,看看回傳結果是不是我們想要的~

    (關於這些 Odata 的寫法,我在第一篇文章有說明,忘記的可以回去看看)


    它顯示的 "Request URL" 長得像這樣:
    https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?%24filter=Direction%20eq%201&%24format=JSON

    這是以下這句經過 URL 編碼後的結果:
    (程式中 requests 會自動幫我們編碼,因此輸入底下這句也可以)
    https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&$format=JSON


    接下來將這些代入程式中:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    function doGet() {
      var response = UrlFetchApp.fetch(
        "https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&$format=JSON",
        {method: 'GET', 'headers': GetAuthorizationHeader()}
      );
      // console.log(response.getResponseCode());
      outData = JSON.parse(response.getContentText());
      console.log(outData);
      return ContentService.createTextOutput(JSON.stringify(outData)).setMimeType(ContentService.MimeType.JSON);
    }
    

    點擊上方的 "執行",程式執行後會自動開啟 "執行記錄",程式碼中 console.log(); 的部分會在此顯示出來。

    如此即可順利取得資料 🎉🎉🎉

    執行 GAS 程式
    "執行" GAS 程式

    完整 Google Apps Script 程式範例

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    function doGet() {
      var response = UrlFetchApp.fetch(
        "https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&$format=JSON",
        {method: 'GET', 'headers': GetAuthorizationHeader()}
      );
      // console.log(response.getResponseCode());
      outData = JSON.parse(response.getContentText());
      console.log(outData);
      return ContentService.createTextOutput(JSON.stringify(outData)).setMimeType(ContentService.MimeType.JSON);
    }
    
    function GetAuthorizationHeader() {
      var AppID = '<YOUR APP ID>';
      var AppKey = '<YOUR APP KEY>';
      var xdate = new Date().toGMTString();
      //HMAC-SHA1 運算
      var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1, "x-date: " + xdate, AppKey);
      //轉成Base64
      var HMAC = Utilities.base64Encode(signature);
      var Authorization = 'hmac username=\"' + AppID + '\", algorithm=\"hmac-sha1\", headers=\"x-date\", signature=\"' + HMAC + '\"';
      return { 'Authorization': Authorization, 'x-date': xdate ,'Accept-Encoding': 'gzip'};
    }
    

    部署

    Google Apps Script 特別的地方就在於可直接把程式部署起來,不需要另外找伺服器、線上服務來處理,非常方便。


    像是上面範例的 function doGet(),就是 Google Apps Script 內定的函式,當我們發佈成 "網頁應用程式" 後,對網址發送 GET 請求(就是在瀏覽器上前往此網址),就會執行此函式。
    另外也有 function doPost() 對應 POST 請求。

    如果想在網址後方帶入參數,像是這樣:
    https://webdomain.com?stationId=1000

    就使用這種寫法,即可取到對應參數後方的字串:
    var stationId = e.parameter.stationId;

    帶入參數
    帶入參數


    那我們開始來 "部署" 吧~

    確認檔案存檔後(重要!!),點擊右上角的 "部署" > "新增部署作業" 按鈕。

    選擇新增部署作業
    選擇 "部署" > "新增部署作業"

    左邊齒輪形狀的設定打開,選擇 "網頁應用程式"。

    選擇網頁應用程式
    選擇 "網頁應用程式"

    "執行身分" 和 "誰可以存取" 可以自己看需求更改,執行 "部署"。

    執行部署
    執行部署

    用這邊產生的網址,到瀏覽器貼上,就可以取得剛剛的資料了~

    網頁應用程式 網址
    網頁應用程式 網址

    * 如果有編輯,需要存檔後再 "部署" 一次,而且網址會更改。但舊版本還會存在,需要到 "管理部署作業" 將其封存。


    部署成網頁

    除了像上述的方法當成一支 API,也可以回傳 HTML,顯示成網頁喔~

    左邊檔案新增一個 HTML。

    新增 HTML 檔案
    新增 HTML 檔案

    HTML 檔案內容撰寫完成後,在原先的程式碼 doGet() 中,回傳這個 HTML 檔案即可。
    (index 是 HTML 的檔名)

    回傳 HTML
    回傳 HTML
    1
    2
    3
    
    function doGet() {
      return HtmlService.createHtmlOutputFromFile('index');
    }
    

    因此你可以在 Google Apps Script 裡,取得 PTX 平台大眾運輸資料後,顯示到自製的網頁上,嘗試做一個🚅查詢時刻表的網頁服務吧~


    其他程式範例

    除了參考我上面的 Google Apps Script 範例,PTX 官方也提供不同程式語言的範例程式碼提供開發者下載 (GitHub)。

    • 平台提供
      • ASP.NET
      • Java
      • JavaScript
    • 網友提供
      • Bourne Shell
      • C# 與 .NET Standard 2.0
      • Go
      • Go Client SDK - Code generated by go-swagger
      • Node.js
      • python
      • Ruby
      • Swift
      • PHP
      • Postman

    結語

    有關更多 Google Apps Script 語法說明,歡迎參考 Google Apps Script 官方文件


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




    參考:
    公共運輸整合資訊流通服務平台 | 官網
    PTX 資料服務使用注意事項 | GitHub
    PTX 官方範例程式碼 | GitHub
    Google Apps Script 官方文件


    我不是神童,只是堅持打好每一顆球。

    —— 林昀儒 (台灣桌球國手)


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

    Jia
    作者
    Jia
    軟體工程師 - Software Engineer