後端工程 Portfolio
CPBL Analytics
從零打造的棒球數據系統
雙資料源 ETL、RESTful API、互動式 Dashboard、自動化 CI/CD
377
場比賽
112K
逐球事件
13
API Endpoints
168
測試
84%
覆蓋率
每日
自動更新
球員查詢
輸入球員名稱查看個人分析數據分析文章
7 篇深度解析LOB%
誰是 2025 CPBL 最幸運的投手? LOB% 解密
用殘壘率拆解 77 位投手的運氣成分 — 後勁的低 ERA 能持續嗎?力亞士其實…
疲勞曲線
投手第幾球開始崩盤? 2025 CPBL 疲勞曲線分析
從 38 位先發投手的逐球數據中,找出疲勞閾值 — 魔神樂 31 球就衰退,後勁…
關鍵時刻
關鍵時刻誰最可靠? 2025 CPBL Clutch 打者排行
用 Clutch Score 量化 62 位打者在高壓情境下的真實表現 — 以及…
wRC+
wRC+ 評級重排: 樂天打者被低估了嗎?
用公園因子校正後,打者真實價值大洗牌 — 樂天龍王、大巨蛋冤大頭名單…
Park Factor
大巨蛋真的壓制打擊嗎? 2025 CPBL 球場因子全解析
用 Park Factor 量化 7 座球場對打擊的影響 — 樂天桃園 PF=1…
BABIP
運氣還是實力? 2025 CPBL BABIP 回歸分析
74 位打者的上半季 BABIP vs 下半季打擊率變化 — 高 BABIP 打…
半季分割
下半季誰爆發、誰崩盤? 2025 CPBL 半季分割分析
74 位打者的上下半季 wOBA 變化 — 朱育賢下半季大爆發,張仁瑋從明星賽後…
工程架構
CPBL 官網 API
POST /getlive
POST /getlive
Python ETL
合併 + 驗證 + 冪等寫入
→合併 + 驗證 + 冪等寫入
SQLite (WAL)
9 tables / 140K rows
→9 tables / 140K rows
分析引擎
4 模組 + 6 計算腳本
→4 模組 + 6 計算腳本
242 JSON
靜態匯出
→靜態匯出
Cloudflare Pages
Global CDN
Global CDN
GitHub Actions 每日 06:00 (台灣) 自動執行完整管線
Key Technical Decisions
為什麼用 SQLite?
14 萬行資料,SQLite 綽綽有餘且零維護。WAL mode 支持讀寫並行。
為什麼分 batter_box 和 PA 兩層?
彙總表(AVG/OPS)和事件表(RE24/Clutch)粒度不同。batter_box 還有來源獨有的 LOB 欄位。
雙資料源怎麼合併?
用 (game_date, home_team, away_team) 做 game-level 對齊。CPBL 缺 player_id,建 player_mapping 表對照。
為什麼靜態 JSON 不用即時 API?
棒球資料每日只更新一次。靜態匯出 = CDN 分發,零伺服器成本,延遲 < 50ms。
冪等 ETL 怎麼做?
INSERT OR IGNORE + UNIQUE constraint。重跑不會產生重複資料。
小樣本怎麼處理?
min_pa/min_ip 動態門檻:賽季初鬆(PA≥20),滿季收緊(PA≥50)。
Tech:Python 3.12|FastAPI|SQLAlchemy|SQLite|ECharts|Tailwind|Docker|GitHub Actions|Cloudflare Pages