iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
Modern Web

每天一點 API:打造我的生活小工具系列 第 13

Day13 — API 資料怎麼存?CSV、JSON、SQLite 練習

  • 分享至 

  • xImage
  •  

API 回來的資料要怎麼存?又為什麼要存?

今天我就要來學習資料存取,了解 CSV 、 JSON 還有 SQLite 的差異,並實作把 API 回傳的 JSON 存成 CSV,讓資料能方便保存與重複使用。

為什麼要學資料存取?

  1. 幾乎所有軟體專案都要存資料

不管是網站、手機 App,還是後端系統,都是需要把資料記錄下來並且讀出來。

  1. 不同資料格式適合不同場景

我們可能會用文字檔、Excel、資料庫,各種不同格式和方式,所以要學會怎麼選擇和操作。

  1. API 回傳的資料多是 JSON 格式

但通常別人要用資料時,不會直接用 JSON,可能會轉成 Excel、報表,或放到查詢系統裡。

  1. 因此需要學會
  • 讀取 API 的 JSON 資料

  • 把資料轉換成別人方便使用的格式

  • 存成檔案或寫入資料庫,方便日後使用

CSV、JSON、SQLite 三者差異簡單比較

CSV(逗號分隔值)

  • 純文字檔案,用逗號分隔資料,像 Excel 一樣的表格

  • 非常輕量,方便匯出和匯入

  • 只能存放表格形式的資料,不適合複雜資料結構

  • Excel 很方便,可以直接開啟編輯

JSON(JavaScript 物件表示法)

  • 網路上 API 最常見的資料格式

  • 支援巢狀資料,比如一個欄位裡面還有子物件或陣列

  • 適合用來系統間資料交換與傳輸

  • 不方便直接用 Excel 打開,也不適合直接用 SQL 查詢

SQLite(輕量型檔案資料庫)

  • 是一個可以存資料的資料庫,但儲存在單一檔案裡

  • 支援用 SQL 語法查詢資料,功能完整,可以做複雜數據處理

  • 需要寫 SQL,操作比 CSV、JSON 複雜一點

  • 適合需要查詢或管理大量資料的情況

小實作:把 API 的 JSON 存成 CSV

步驟 1:呼叫 API 取得 JSON

  • 使用 JSONPlaceholder 的users資料。

  • 練習取得一組清單資料。

import csv
import requests

API = "https://jsonplaceholder.typicode.com/users"

def fetch_users(timeout=10):
    r = requests.get(API, timeout=timeout)
    r.raise_for_status()
    return r.json()  # list of dicts
def main():
    try:
        users = fetch_users()
    except requests.exceptions.RequestException as e:
        print("API 錯誤:", e)
        return

步驟 2:挑選欄位

  • 只挑常用的(id、name、email、city、company.name)。

  • 巢狀結構要「扁平化」成一維欄位。

    # 選擇想輸出的欄位(含巢狀欄位)
    columns = [
        "id", "name", "username", "email",
        "address.city", "address.zipcode",
        "phone", "website",
        "company.name"
    ]
    def pick(obj, path, default=""):
        # 取巢狀欄位用:e.g. path="address.city"
        cur = obj
        for key in path.split("."):
            if isinstance(cur, dict) and key in cur:
                cur = cur[key]
            else:
                return default
        return cur

    rows = []
    for u in users:
        row = {col: pick(u, col) for col in columns}
        rows.append(row)

步驟 3:寫入 CSV

  • 使用 csv.DictWriter

  • 注意 Windows Excel 要加 utf-8-sig

  • 寫 header、再寫 rows。

    # Windows 用 Excel 開 CSV:建議用 utf-8-sig + newline=''
    out_path = "users.csv"
    with open(out_path, "w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(f, fieldnames=columns)
        writer.writeheader()
        writer.writerows(rows)

    print(f"已輸出 {len(rows)} 筆到 {out_path}")

if __name__ == "__main__":
    main()

執行結果:

已輸出 10 筆到 users.csv

這個users.csv,我是用 Excel 就打開的。

把 CSV 寫進 SQLite

為什麼要這麼做?

  • CSV 是純文字檔,適合簡單表格資料,但不方便做複雜查詢。

  • 把 CSV 資料存進 SQLite 資料庫後,可以用 SQL 查詢分析資料,很方便。

  • SQLite 是輕量型資料庫,檔案就一個檔,適合本地使用。

步驟 1:匯入套件與 API 設定

import sqlite3
import requests

API = "https://jsonplaceholder.typicode.com/users"

步驟 2:取資料

def fetch_users(timeout=10):
    r = requests.get(API, timeout=timeout)
    r.raise_for_status()
    return r.json()
def main():
    users = fetch_users()

先抓回 users 清單,等等要存進資料庫。

步驟 3:開資料庫

    conn = sqlite3.connect("day13.db")
    cur = conn.cursor()

步驟 4:建表

  • 建立users表,欄位包含基本資訊與扁平化後的欄位。
    cur.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT,
        username TEXT,
        email TEXT,
        city TEXT,
        zipcode TEXT,
        phone TEXT,
        website TEXT,
        company TEXT
    )
    """)
    conn.commit()

步驟 5:取巢狀欄位

def pick(d, path, default=""):
        curv = d
        for k in path.split("."):
            if isinstance(curv, dict) and k in curv:
                curv = curv[k]
            else:
                return default
        return curv

步驟 6:轉成扁平列

    rows = []
    for u in users:
        rows.append((
            u.get("id"),
            u.get("name",""),
            u.get("username",""),
            u.get("email",""),
            pick(u, "address.city"),
            pick(u, "address.zipcode"),
            u.get("phone",""),
            u.get("website",""),
            pick(u, "company.name")
        ))

步驟 7:UPSERT(避免重複跑程式時報錯)

    cur.executemany("""
    INSERT INTO users (id, name, username, email, city, zipcode, phone, website, company)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    ON CONFLICT(id) DO UPDATE SET
      name=excluded.name,
      username=excluded.username,
      email=excluded.email,
      city=excluded.city,
      zipcode=excluded.zipcode,
      phone=excluded.phone,
      website=excluded.website,
      company=excluded.company
    """, rows)

    conn.commit() # 提交
    conn.close() # 關閉
    print(f"已寫入 SQLite:{len(rows)} 筆 → day13.db")

if __name__ == "__main__":
    main()

執行結果:

已寫入 SQLite:10 筆 → day13.db

查驗一下:

import sqlite3
conn = sqlite3.connect("day13.db")
cur = conn.cursor()
for row in cur.execute("SELECT id, name, city, company FROM users ORDER BY id LIMIT 5"):
    print(row)
conn.close()

執行結果:

(1, 'Leanne Graham', 'Gwenborough', 'Romaguera-Crona')
(2, 'Ervin Howell', 'Wisokyburgh', 'Deckow-Crist')
(3, 'Clementine Bauch', 'McKenziehaven', 'Romaguera-Jacobson')
(4, 'Patricia Lebsack', 'South Elvis', 'Robel-Corkery')
(5, 'Chelsey Dietrich', 'Roscoeview', 'Keebler LLC')

為什麼要查驗?

  1. 確認資料真的寫進去了
    雖然呼叫了 INSERT,但沒查出來看一下,不能保證資料表裡有東西。

  2. 確認格式正確
    比如 city、company 有沒有存成文字?id 有沒有是數字?這些都能藉由查詢前幾筆檢查。

  3. 避免後面錯誤越來越大
    如果一開始就發現資料欄位錯、順序錯,馬上修正比等到之後大量查詢或分析再回頭修省時省力得多。

今日總結

  • 了解了CSV 、 JSON 和 SQLite 的差異。

  • 完成把 API 存成 CSV 的小練習。

  • 認識如何把資料存進 SQLite,方便查詢。


上一篇
Day 12 — 日曆 API:API 失敗也能顯示正確星期
系列文
每天一點 API:打造我的生活小工具13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言