用 n8n 每 10 分鐘抓一次臺北市 YouBike 2.0 即時資料,驗證後存到 Google Drive;整個工作流由 Claude Code 在 VS Code 裡寫好、用 Docker 部署。這是一門從零開始的 n8n 入門實作。
補充課・2026-09-25 新增
老師新錄了一支 13 分鐘的影片,不教按鈕,講動手之前的規劃:用軟體開發生命週期的角度,從探索、提案、規格、設計到任務清單,每一步都寫下理由和怎麼驗證。想知道為什麼節點長這樣、為什麼不用帳密、為什麼快照判斷寫成「分鐘 < 10」,先看這一頁。
第 1 節
老師本身專攻資料庫與商業智慧,資料清洗、轉換的流程很熟,但 n8n 之前只裝好沒真的用過。這堂課的想法是:讓 AI Agent 直接幫你設定 n8n 工作流,並且自動部署和測試。拿來練手的題目,是抓臺北市 YouBike 2.0 的即時站點資料,按時間存進 Google Drive。
| 檔案 | 多久更新 | 用途 |
|---|---|---|
ubike_latest.json | 每 10 分鐘覆蓋一次 | 永遠是最新一份,給要看「現在狀況」的程式讀 |
ubike_YYYYMMDD_HH00.json | 每小時一份(整點那次) | 保留歷史,日後分析使用量變化 |
資料原樣保存、不改欄位。抓回來的東西如果不是合法 JSON 或是空的,這次執行就直接失敗,Drive 上原本的好檔案不會被壞資料蓋掉。
第 2 節
左邊是觸發器,每 10 分鐘叫一次;中間抓資料、驗證;驗證過了分成兩條支線同時處理。
🔍 點圖放大
🔍 點圖放大
ubike_latest.json,有就覆蓋、沒有就建立。ubike_YYYYMMDD_HH00.json 快照。
🔍 點圖放大
ubike_20260925_0900.json,原因在第 5 節「目前的限制」。第 3 節
*/10 * * * *,每小時 0、10、20…50 分各跑一次,一天 144 次。它本身不帶資料,只是「開始」的訊號。youbike_immediate.json;逾時 30 秒、失敗重試 3 次、每次隔 5 秒。回應故意用「文字」接收,不讓 n8n 自動拆成上千筆,整份資料只算一筆,後面只要處理一次。alwaysOutputData:找不到也要往下走,不然第一次執行會卡在這裡。ubike_20260925_1400.json 這種檔名上傳,每小時新增一個,不覆蓋舊的。
🔍 點圖放大
第 4 節
n8n 的 executionOrder: v1 規則是:分岔時先把一條支線跑到底,再跑下一條,順序看節點在畫布上的位置由上而下。支線 A 在上面,所以一定先處理 latest,再處理整點快照。
🔍 點圖放大
🔍 點圖放大
ubike_latest.json 維持 1 個檔、被覆蓋 144 次;快照新增 24 個檔。第 5 節
| 可能的狀況 | 保護機制 | 結果 |
|---|---|---|
| API 暫時沒回應或很慢 | 逾時 30 秒、重試 3 次 | 多數會重試成功;都失敗就本次失敗 |
| API 回傳錯誤頁或截斷的 JSON | 第 3 步 JSON 解析失敗就 throw | 不寫入,Drive 保留上次的正確資料 |
| API 回傳空陣列 | 第 3 步陣列檢查 | 不寫入 |
| 第一次執行,Drive 還沒有 latest 檔 | 第 4 步 alwaysOutputData | 走「建立」分支 |
| latest 檔被丟進垃圾桶 | 搜尋條件排除垃圾桶 | 視為不存在,重新建立 |
| 排程延遲幾分鐘 | 整點判斷用分鐘 < 10 | 快照不會漏 |
| 還沒完成 Google 授權 | — | Drive 節點失敗:Unable to sign without access token |
第 6 節
🔍 點圖放大
| 項目 | 說明 |
|---|---|
| 憑證 | Drive 節點都引用同一個 OAuth2 憑證「Google Drive (Ubike)」,容器首次啟動時由範本檔配合 .env 的 Client ID/Secret 產生 |
| 環境變數 | 第 4、8、10 步用 $env.UBIKE_FOLDER_ID 取資料夾,換資料夾只要改 .env 再重啟 |
| 工作流更新 | 容器每次啟動都用映像裡的 JSON 蓋掉工作流。要改流程請改 workflows/ubike-drive-sync.json 再 docker compose up -d --build;直接在 n8n 畫面上改的,下次重啟就會被蓋掉 |
| OAuth 回呼網址 | http://localhost:5679/rest/oauth2-credential/callback,要和 Google Cloud Console 登記的完全一致 |
"active": false,畫面上卻是 Active?這是刻意的:檔案裡保持停用,容器啟動時由 entrypoint.sh 匯入後再執行 n8n update:workflow --active=true 開起來。所以「以 git 裡的 JSON 為正本」本來就是這套設計。
🔍 點圖放大
第 7 節