200の選択肢より、今夜のいいプランをひとつ
今夜パリで開かれるイベントを、文化圏とカテゴリー別にまとめた無料の地図。選択肢に埋もれず、選びやすくするためのものです。
ニーズ
忙しい一週間のあと、出かけたい気持ちはあっても、何百ものイベントを眺めるのは疲れます。選択肢が多すぎると、結局家にいることになりがちです。
アイデア
問題は選択肢が少ないことではなく、多すぎることです。そこでこのアプリは、一覧から始めるのではなく、「今夜、近くで何ができる?」というひとつの問いから始まります。
つくったもの
- 今夜のイベントを地図上ですぐに表示するサイト。まずスマートフォンでの利用を前提に設計しました。
- パリ市のオープンデータ、パリにある外国の文化機関(FICEP)、その他の公開フィードからイベントを集め、情報源ごとの周期で更新する自動収集の仕組み。
- その日の気分で選べるよう、文化圏とカテゴリーごとに見て回れる機能。
- 安全策:情報源がひとつ止まっても最後の正常なデータを表示し続け、ステータスページは停止する代わりに「低下」と表示します。
成果
- 27,623データベース内のイベント数(2026年10月6日時点)
- 0地図上に位置がないイベント
- 4自動で統合しているオープンデータ・会場フィードの情報源(2026年10月6日時点)
2026年8月23日から eventmap.hamdy-tabsissi.com で公開しています。データベースのすべてのイベントが地図上に表示され、データは自動で更新されます。
画面で見る
学んだこと
製品を設計する前に、データを確かめること。情報源をざっと調べたところ、ナンテールは0件、モントルイユは14件でした。そこで壊れやすいスクレイピングを維持するのではなく、対象をパリに絞りました。また、静かな不具合は停止よりも高くつきます。日付を文字列として比較していたため、一部のイベントが気づかれないまま抜け落ちていましたが、テストで発見しました。
技術的な詳細 技術スタック、アーキテクチャ、設計判断(技術職の方向け)
技術スタック
- Python (FastAPI, asyncio)
- SQLite
- Leaflet + OpenStreetMap
- nginx
- systemd
- Ubuntu 22.04
アーキテクチャの全体像
- 訪問者のスマートフォンまたはブラウザ
- nginx — リバースプロキシ、セキュリティヘッダー
- FastAPI アプリ(uvicorn) — 127.0.0.1 のみで待ち受ける systemd サービス、CPU とメモリの上限つき
- SQLite — イベント、情報源、重複の除去
- 6時間ごとの自動収集 ← パリ市のオープンデータ + FICEP(OpenAgenda)
仕組み
- 複数の公開フィード(パリ市の Que faire à Paris〔ODbL ライセンス〕、FICEP、OpenAgenda〔.ics〕など)を asyncio で非同期に取り込み、重複を除いて SQLite に保存。稼働中の情報源の一覧は /health にあります。
- 情報源ごとの耐障害性のある更新:失敗した情報源が既存データを消すことはなく、/health が情報源ごとの状態を返して「degraded」に切り替わります。
- 郊外の13サイトを調査した結果、利用できるフィード(.ics も JSON-LD Event も)がなかったため、対象をナンテール〜パリ〜モントルイユからパリに絞りました。複数ソース対応の構成はそのまま残しています。
- 分離されたサービス:シェルを持たない専用のシステムユーザー、systemd による CPU とメモリの上限、nginx の背後で 127.0.0.1 のみに待ち受けるアプリケーション。
- テストで見つけた不具合:日付を文字列として比較していたため、本番環境で一部のイベントが黙って除外されていました。修正し、記録に残しています。
発生した問題と対処
- 2026年9月24日から10月5日まで、サーバーからパリ市のフィードに接続できませんでした(DNS エラー)。EventMap は最後の正常なデータを配信し続け、/health は情報源を明示して「degraded」を返していました。フィードが復旧すると、データベースの制約(削除対象の行を指す重複データ)のせいで更新が毎回黙って失敗し、/health は誤って「ok」を返していました。ローカルで再現して修正し、2つのテストで検証したうえで当日中に再デプロイ。16,160件のイベントが更新されました。
まだ足りない点
- 対象はパリのみ
- 公開オープンデータの品質に依存