安排每日資料拉取

將該請求放入一個附加寫入檔案的小指令碼,並用 cron 每天執行一次:每天拉取黃金和 USD/IDR 共 2 次請求,每月約 62 次。每日數值帶有 00:00 UTC 的時間戳記,因此請在 UTC 午夜之後執行。

用 API 排程抓取資料

金價請求和匯率請求使用同一把 Narwhal API 金鑰。腳本帶著 Authorization: Bearer YOUR_KEY 請求標頭把每個請求發送到 https://api.narwhalapi.com,然後將傳回的值附加到 daily.csv。該檔案會同時保留抓取時間、以美元計的金價和 USD/IDR 匯率。

  1. 把金鑰放進環境檔 取得一把免費金鑰,把 export NARWHAL_API_KEY=... 寫入 ~/.narwhal.env。將該檔案的權限設為 600,這樣只有你能讀取;排程執行的指令會在啟動 Python 之前先載入這個檔案。
  2. 儲存每日抓取腳本 將其儲存為 /home/me/daily_pull.py。當 daily.csv 是新檔案時,腳本會先寫入欄位名稱;請求成功後,再附加一列包含 run_at_utc、xau_usd 和 usd_idr 的資料。
    Python:將金價和 USD/IDR 附加到 CSV
    #!/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"],
            ]
        )
  3. 新增每日 cron 項目 在 UTC 伺服器上,用這條 crontab 項目把抓取安排在 UTC 午夜之後。它從環境檔讀取金鑰,並把腳本的輸出和錯誤寫入 /home/me/daily_pull.log。
    UTC 伺服器上的每日 cron 項目
    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 中,抓取時間排在最前,隨後依標題列設定的順序依序是金價和匯率。

2026 年 10 月 24 日的 CSV 列
run_at_utc,xau_usd,usd_idr
2026-10-24T12:17:15Z,3996.00,18107.8

發布於 。

後續步驟