アーキテクチャ
プロジェクト構成
HorseRacingDataChecker/
├── .env.example # 設定テンプレート
├── .gitignore
├── requirements.txt # Python依存パッケージ
├── main.py # エントリポイント・ポーリングループ
├── config.py # 設定ロード (dataclass + dotenv)
├── scraper/ # データ取得層
│ ├── __init__.py
│ ├── race_calendar.py # 当日レーススケジュール取得
│ ├── odds_fetcher.py # オッズJSON API取得
│ └── horse_info.py # 馬名・騎手名取得
├── analyzer/ # 分析層
│ ├── __init__.py
│ ├── snapshot_store.py # スナップショット管理 (SQLite + in-memory)
│ └── change_detector.py # 変動率計算・急騰/急落判定
├── notifier/ # 出力層
│ ├── __init__.py
│ ├── terminal_display.py # ターミナルダッシュボード
│ └── slack_notifier.py # Slack Webhook通知
├── data/ # SQLite DB (自動生成)
└── docs/ # VitePress設計書レイヤー構成
┌─────────────────────────────────────┐
│ main.py │ ← オーケストレーション層
│ (ポーリングループ / CLI) │
├──────────┬──────────┬───────────────┤
│ scraper/ │ analyzer/│ notifier/ │
│ データ取得│ 分析 │ 出力 │
├──────────┼──────────┼───────────────┤
│ requests │ SQLite │ rich │
│ BS4 │ deque │ Slack Webhook │
└──────────┴──────────┴───────────────┘
↓ ↓ ↓
netkeiba.com odds.db Terminal/Slack設計原則
1. 層の分離
- scraper: 外部サイトからのデータ取得に専念。パース・変換まで担当
- analyzer: ビジネスロジック(変動率計算、閾値判定)。外部依存なし
- notifier: 出力先の違いを吸収。新しい通知先の追加が容易
2. ハイブリッドストレージ
- in-memory deque: 直近2件のみ保持。リアルタイム比較が O(1)
- SQLite: 全履歴を永続化。後からの分析や可視化に対応
3. 耐障害性
- 個別レースのエラーは無視して他レースの監視を継続
- Ctrl+C でグレースフルシャットダウン
- レート制限対策のリクエスト間隔制御
4. 設定の外部化
.envファイルで全設定を管理- CLIオプションで実行時上書き可能
依存ライブラリ
| ライブラリ | バージョン | 用途 |
|---|---|---|
| requests | >=2.32.0 | HTTP通信 |
| beautifulsoup4 | >=4.12.0 | HTML解析 |
| lxml | >=5.0.0 | BS4パーサーバックエンド |
| rich | >=13.0.0 | ターミナルUI |
| python-dotenv | >=1.0.0 | .env読み込み |