將該請求放入一個附加寫入檔案的小指令碼,並用 cron 每天執行一次:每天拉取黃金和 USD/IDR 共 2 次請求,每月約 62 次。每日數值帶有 00:00 UTC 的時間戳記,因此請在 UTC 午夜之後執行。
用 API 排程抓取資料
金價請求和匯率請求使用同一把 Narwhal API 金鑰。腳本帶著 Authorization: Bearer YOUR_KEY 請求標頭把每個請求發送到 https://api.narwhalapi.com,然後將傳回的值附加到 daily.csv。該檔案會同時保留抓取時間、以美元計的金價和 USD/IDR 匯率。
- 把金鑰放進環境檔 取得一把免費金鑰,把
export NARWHAL_API_KEY=...寫入~/.narwhal.env。將該檔案的權限設為600,這樣只有你能讀取;排程執行的指令會在啟動 Python 之前先載入這個檔案。 - 儲存每日抓取腳本 將其儲存為
/home/me/daily_pull.py。當daily.csv是新檔案時,腳本會先寫入欄位名稱;請求成功後,再附加一列包含run_at_utc、xau_usd和usd_idr的資料。#!/usr/bin/env python3 """Append today's gold price and USD/IDR rate to daily.csv. Run it once a day.""" import csv, os, pathlib from datetime import datetime, timezone import requests API = "https://api.narwhalapi.com/v1" H = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"} gold = requests.get(f"{API}/commodities/spot/XAU/USD", headers=H, timeout=10) fx = requests.get( f"{API}/fx/rates/USD", params={"currencies": "IDR"}, headers=H, timeout=10 ) gold.raise_for_status() # a failed run exits non-zero, so cron mail or your monitor sees it fx.raise_for_status() path = pathlib.Path("daily.csv") new = not path.exists() with path.open("a", newline="") as f: w = csv.writer(f) if new: w.writerow(["run_at_utc", "xau_usd", "usd_idr"]) w.writerow( [ datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), gold.json()["price"], fx.json()["rates"][0]["rate"], ] ) - 新增每日 cron 項目 在 UTC 伺服器上,用這條 crontab 項目把抓取安排在 UTC 午夜之後。它從環境檔讀取金鑰,並把腳本的輸出和錯誤寫入
/home/me/daily_pull.log。15 1 * * * . $HOME/.narwhal.env && /usr/bin/python3 /home/me/daily_pull.py >> /home/me/daily_pull.log 2>&1
每個請求的逾時時間為 10 秒。腳本從回應的 price 欄位讀取金價,從 rates 中的 rate 欄位讀取 USD/IDR,並把兩個值寫入同一列。之後的每次抓取都是附加到檔案中,只有檔案是新建時才寫入欄位標題。
crontab 中寫入環境檔的路徑,金鑰則保留在 NARWHAL_API_KEY 中。Narwhal 的各個資料 API 共用一個帳戶、一個 API 金鑰和一份餘額,因此排程的黃金和匯率請求都從該餘額中扣款。回應帶有 X-RateLimit-Remaining,表示剩餘的速率限制額度。
run_at_utc 欄記錄指令碼寫入該列的時間,請將其視為拉取時間。每日數值帶有 00:00 UTC 的時間戳記,因此把檔案附加安排在 UTC 午夜之後,可使每日任務與資料採用相同的時間基準。
不寫程式排程流程
每日流程可以由 n8n 的 Schedule Trigger、Make 的「Schedule」或 Zapier 的「Schedule by Zapier」啟動。用 Google Sheets 的附加列來儲存結果。如果你希望把數值放進試算表而不是腳本的 CSV 檔案,這就是每日抓取的試算表去向。
排程觸發器每天啟動該流程;附加列會儲存該次拉取的結果。請使時間與 UTC 保持一致,因為每日數值帶有 00:00 UTC 的時間戳記。排程流程與指令碼遵循相同的每日時間安排,排程和儲存都在流程中處理。
對於排程執行的腳本,其他排程方式還有 Windows 的工作排程器、macOS 的 launchd 或雲端排程器。每天的任務仍然是金價請求和 USD/IDR 請求。請選擇與腳本執行位置相符的排程器;沒有伺服器時,則使用排程流程。
各種情況適合的方式
| 情況 | 最適合的方式 | 原因 |
|---|---|---|
| 隨時開機的伺服器或筆記型電腦 | cron | 在那台機器上執行每日腳本 |
| 沒有伺服器 | 依排程執行的 n8n、Make 或 Zapier | 啟動每日流程並將結果附加到 Google Sheets |
| 資料隨事件而非時間變化 | Webhook | 透過事件驅動的方式接收資料 |
cron 使用哪個時區?
cron 使用伺服器的時區。用 date 查看伺服器時間,並使用 UTC 以便與資料一致。這條 crontab 項目假定伺服器使用 UTC,其「午夜之後」的執行時間也取決於該時區。
外匯日匯率帶有 00:00 UTC 的時間戳記。該時間戳記與指令碼的 run_at_utc 欄表示不同的時間:日匯率有其資料時間戳記,而 CSV 記錄的是拉取時間。商品和外匯價格為即時,因此每一列儲存的是指令碼執行那一刻的價格。
如果某天的執行失敗了怎麼辦?
請求失敗時,腳本以非零狀態碼結束,並且不會附加任何內容。只有兩個請求都成功後,腳本才會開啟 daily.csv 附加該列。因此請求失敗的那次執行,不會在檔案中留下紀錄。
cron 郵件或監控工具可以發現非零結束狀態。請增加警示,或在失敗後重新執行腳本;商品價格警示是相關的警示教學。該 cron 項目還會把輸出和錯誤寫入命令中指定的記錄檔。
對於請求限制類錯誤,請區分帶有 Retry-After 的 429 rate_limit_exceeded 與需要等到你儲值後才能解決的 402 insufficient_credits。排程抓取中的這部分處理,請參閱快取與 429 處理。錯誤回應使用 application/problem+json,包含 status、code、detail 和 request_id。
計算範例:一個月的每日抓取
每次每日抓取都要計入金價請求和 USD/IDR 請求,再乘以當月的天數。每天 2 個請求、共 31 天,腳本一共呼叫 62 次,依每 1,000 次 $2 計算,約為 $0.12。
| 計算 | 結果 |
|---|---|
| 金價請求加 USD/IDR 請求 | 每天 2 個請求 |
| 2 個請求 × 31 天 | 62 個請求 |
| 62 × $2 ÷ 1,000 | 約 $0.12 |
2026 年 10 月 24 日,抓取時間為 2026-10-24T12:17:15Z 的一列中,金價為 3996.00 USD,USD/IDR 為 18107.8。在 CSV 中,抓取時間排在最前,隨後依標題列設定的順序依序是金價和匯率。
run_at_utc,xau_usd,usd_idr
2026-10-24T12:17:15Z,3996.00,18107.8發布於 。