使用 Python 取得世界銀行資料

Narwhal API 索引了 1,489 個採用 CC BY 4.0 授權的世界銀行 WDI 年度指標。若要在 Python 中取得世界銀行資料,請搜尋指標、在其 ID 範本中加入小寫國家代碼,再使用 API 金鑰請求觀測資料。回應包含期間、十進位字串數值、來源標示及授權網址。方案會決定可存取的歷史期間,以及每日未快取資料擷取額度。

使用 API

  1. 取得免費金鑰並準備 Python 環境 在註冊頁面建立帳號、取得 API 金鑰,並在執行 Python 的 shell 中設定 NARWHAL_API_KEY。請將預留位置替換為你的金鑰。安裝用於 HTTP 呼叫的 requests,以及用於 DataFrame 的 pandas。每次請求都在 Authorization 標頭中使用金鑰;最後一步的完整程式會從環境中讀取金鑰。
    安裝相依套件並設定金鑰
    python -m pip install requests pandas
    export NARWHAL_API_KEY="replace-with-your-key"
  2. 搜尋指標 使用 source=wdi 在目錄中搜尋 gdp per capita。印出每筆結果的 id_template 與標題,再選擇需要的指標。所有方案皆可使用目錄搜尋,且不會呼叫來源。params 引數會處理搜尋詞中的空格。搜尋結果描述的是指標;國家應放在下一步建立的序列 ID 中。
    尋找世界銀行指標範本
    import os
    import requests
    
    BASE_URL = "https://api.narwhalapi.com"
    headers = {
        "Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"
    }
    response = requests.get(
        f"{BASE_URL}/v1/economics/catalogue",
        headers=headers,
        params={"q": "gdp per capita", "source": "wdi"},
        timeout=10,
    )
    response.raise_for_status()
    catalogue = response.json()
    for hit in catalogue["results"]:
        print(hit["id_template"], hit["title"])
  3. 在範本中加入國家 將所選範本中的 {country} 替換為小寫 ISO 3166-1 alpha-3 代碼。印尼使用 idn。世界銀行 ID 的格式為 wdi:<indicator>/<iso3>,包含指標與國家之間的斜線。透過 id 查詢參數傳入完整 ID。此程式片段會選取第一筆搜尋結果;使用前請先檢查印出的標題。
    建立指定國家的序列 ID
    if not catalogue["results"]:
        raise SystemExit("No matching indicators found.")
    selected = catalogue["results"][0]
    series_id = selected["id_template"].replace("{country}", "idn")
    print(series_id)
  4. 讀取年度觀測資料 請求該 ID 的觀測資料。年度期間使用 YYYY;選填的 start 與 end 皆包含邊界。回應上限最多接受 1,000 筆觀測資料,預設為 100 筆。如果 next_cursor 有值,請將其作為 cursor 傳入以繼續讀取。提高上限不會延長方案可存取的歷史期間,缺漏年份也不會出現在回應中。
    讀取所選序列
    response = requests.get(
        f"{BASE_URL}/v1/economics/catalogue/series/observations",
        headers=headers,
        params={"id": series_id, "limit": 1000},
        timeout=10,
    )
    response.raise_for_status()
    observations = response.json()["observations"]
  5. 建立 DataFrame 使用觀測資料建立 DataFrame,將 period 轉為整數,並將 value 轉為浮點數。數值以十進位字串回傳。需要十進位運算時,請使用 Decimal 取代 float()。分析時請一併保留回應中的單位標籤:指標標題會說明數值衡量的內容。此轉換不會填補缺漏,也不會為缺漏年份建立觀測資料。
    轉換期間與數值
    import pandas as pd
    
    frame = pd.DataFrame(observations, columns=["period", "value"])
    frame["period"] = frame["period"].astype(int)
    frame["value"] = frame["value"].map(float)
    print(frame)
  6. 批次查詢多個國家並處理請求錯誤 執行這份完整程式,讀取範例中的 GDP 序列,並批次查詢印尼與加拿大的最新數值。以逗號串接 ID;最新資料端點接受 1 至 50 個不重複的 ID。每個回傳序列計入一次呼叫,並一次計入用量。程式會印出各國的期間與數值、列出缺漏的 ID,並在收到 400、404 或 429 fetch_limit_reached 回應時顯示錯誤訊息並停止。
    讀取 GDP 歷史資料並批次取得最新數值
    import os
    import requests
    import pandas as pd
    
    BASE_URL = "https://api.narwhalapi.com"
    HEADERS = {
        "Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"
    }
    
    def get_json(path, params):
        response = requests.get(
            f"{BASE_URL}{path}",
            headers=HEADERS,
            params=params,
            timeout=10,
        )
        try:
            response.raise_for_status()
        except requests.HTTPError:
            problem = response.json()
            code = problem.get("code", "unknown_error")
            if response.status_code == 429 and code == "fetch_limit_reached":
                retry_after = response.headers.get("Retry-After")
                raise SystemExit(
                    f"Uncached fetch allowance used. Retry-After: {retry_after}"
                )
            if response.status_code in (400, 404):
                raise SystemExit(f"{code}: {problem.get('detail', '')}")
            raise
        return response.json()
    
    series_id = "wdi:ny.gdp.mktp.cd/idn"
    rows = []
    params = {"id": series_id, "limit": 1000}
    while True:
        payload = get_json(
            "/v1/economics/catalogue/series/observations", params
        )
        rows.extend(payload["observations"])
        cursor = payload.get("next_cursor")
        if not cursor:
            break
        params["cursor"] = cursor
    
    frame = pd.DataFrame(rows, columns=["period", "value"])
    frame["period"] = frame["period"].astype(int)
    frame["value"] = frame["value"].map(float)
    print(frame)
    
    countries = ("idn", "can")
    ids = [f"wdi:ny.gdp.mktp.cd/{country}" for country in countries]
    batch = get_json(
        "/v1/economics/catalogue/latest",
        {"ids": ",".join(ids)},
    )
    for observation in batch["observations"]:
        country = observation["id"].rsplit("/", 1)[1]
        print(country, observation["period"], observation["value"])
    for missing in batch["missing"]:
        print("Missing:", missing)

如何解讀印尼 GDP 範例?

序列 wdi:ny.gdp.mktp.cd/idn 是以當期美元計價的印尼 GDP。在 27 October 2026 使用 Pro 金鑰並設定 limit=3 的請求,回傳了以下觀測資料。此範例使用 GDP 總額;若需要人均 GDP,請使用目錄搜尋取得的範本。

從 GDP 回應擷取的觀測資料
[
  {"period": "1967", "value": "5667756627.92093"},
  {"period": "1968", "value": "7076465299.81141"},
  {"period": "1969", "value": "8337423312.88344"}
]

對於 1967 年,float("5667756627.92093") 會轉換數值,供 DataFrame 進行數值運算。如果也需要其十進位表示,請保留原始字串。回應包含世界銀行 WDI 來源標示及 CC BY 4.0 授權網址。使用資料時,請一併保留來源標示與授權資訊。

為什麼我的 Free 金鑰只回傳幾年的資料?

Free 可存取最近 12 個月的歷史資料,年度資料則至少提供最新 5 筆觀測資料。Narwhal 會比較方案期間與此最低筆數,採用可提供較多觀測資料的規則。因此,即使大多數資料超出一般期間,年度序列仍會保留數筆觀測資料。年度最低筆數適用於所有方案。

我的方案適用哪個上限:

方案每帳戶每日未快取擷取次數(UTC)歷史資料範圍
免費10最近 12 個月,且至少包含最新 5 筆年度觀測資料
Basic100最近 5 年,且至少包含最新 5 筆年度觀測資料
Pro1,000完整歷史資料

若整個查詢範圍都早於允許的期間,會回傳 403 plan_upgrade_required。對於年度序列,Narwhal 會在載入序列後檢查範圍,以納入最低筆數規則。請參閱方案詳細資訊,選擇符合分析需求的歷史期間。

429 fetch_limit_reached 錯誤代表什麼?

你的帳號已用完每日額度,而此請求需要擷取尚未快取的資料。重試前請先讀取 Retry-After;額度會在 00:00 UTC 重設。達到上限後,已快取的序列仍可回應。世界銀行資料的快取時間介於 24 小時至 7 天,因此再次請求不一定需要擷取資料。

遇到 400 invalid_series_id 時,請檢查指標、斜線及小寫國家代碼。400 invalid_query 表示查詢無效。404 not_found 可能表示索引中沒有該指標;Narwhal 會保留此結果 24 小時。再次請求前,請先將 ID 與目錄搜尋結果核對。

過期資料回應及 400、404、503 回應不計入用量。如果來源無法使用,且沒有快取副本,Narwhal 會回傳 503 upstream_busy,並附上 Retry-After。重試處理方式請參閱快取與 429 處理。

發布於 。

後續步驟