API 回來的資料要怎麼存?又為什麼要存?
今天我就要來學習資料存取,了解 CSV 、 JSON 還有 SQLite 的差異,並實作把 API 回傳的 JSON 存成 CSV,讓資料能方便保存與重複使用。
不管是網站、手機 App,還是後端系統,都是需要把資料記錄下來並且讀出來。
我們可能會用文字檔、Excel、資料庫,各種不同格式和方式,所以要學會怎麼選擇和操作。
但通常別人要用資料時,不會直接用 JSON,可能會轉成 Excel、報表,或放到查詢系統裡。
讀取 API 的 JSON 資料
把資料轉換成別人方便使用的格式
存成檔案或寫入資料庫,方便日後使用
純文字檔案,用逗號分隔資料,像 Excel 一樣的表格
非常輕量,方便匯出和匯入
只能存放表格形式的資料,不適合複雜資料結構
Excel 很方便,可以直接開啟編輯
網路上 API 最常見的資料格式
支援巢狀資料,比如一個欄位裡面還有子物件或陣列
適合用來系統間資料交換與傳輸
不方便直接用 Excel 打開,也不適合直接用 SQL 查詢
是一個可以存資料的資料庫,但儲存在單一檔案裡
支援用 SQL 語法查詢資料,功能完整,可以做複雜數據處理
需要寫 SQL,操作比 CSV、JSON 複雜一點
適合需要查詢或管理大量資料的情況
步驟 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 是純文字檔,適合簡單表格資料,但不方便做複雜查詢。
把 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')
為什麼要查驗?
確認資料真的寫進去了
雖然呼叫了 INSERT,但沒查出來看一下,不能保證資料表裡有東西。
確認格式正確
比如 city、company 有沒有存成文字?id 有沒有是數字?這些都能藉由查詢前幾筆檢查。
避免後面錯誤越來越大
如果一開始就發現資料欄位錯、順序錯,馬上修正比等到之後大量查詢或分析再回頭修省時省力得多。
了解了CSV 、 JSON 和 SQLite 的差異。
完成把 API 存成 CSV 的小練習。
認識如何把資料存進 SQLite,方便查詢。