Next.js と Python を連携する際にぶつかった問題
背景
現在の Python コードは、
- スクレイピング
- Gemini によるデータ整形
までは完成していて、コンソールへの出力はできた状態です。
しかし、Next.js から利用する Web アプリとして考えると、いくつか課題があります。
問題① APIになっていない
現在は結果を print() して終了しています
print(dataList)
Next.js から利用するためには、
- リクエストを受け取る
- JSON を返す
API サーバーが必要です。
解決策
FastAPI を導入する。
@app.post("/api/search")
のようなエンドポイントを作成する。
問題② 会場追加時の拡張性が低い
現在はスクレイパーが Main.py に直接書かれています。
MarineMesseScraper()
会場を追加するたびに、
if venue == ...
が増えてしまい、面倒です。
更に、plantUMLでクラス図を作成してみたところ、せっかく作ったクラスの関係がショボすぎて、これなら関数で十分という機能になっています。
あんまり意味をなしていないクラス関係
解決策
抽象クラスを利用します。
class VenueScraperBase(ABC):
...
各会場のスクレイパーはこれを継承する形で実装してみようと思います。
MarineMesseScraper
ZeppScraper
Main.py は会場の違いを意識せず、
scraper.get_formatted_data()
のような共通メソッドを呼び出すだけになります。多態性(ポリモーフィズム)が実現できるようになります。しかし、サイトによってボタンのクリックが必要でないものもあるので、 @abstractmethod を付けるところには注意が必要と考えています。
問題③ 会場管理が煩雑になる
会場が増えるたびに Main.py を修正する必要があります。
解決策
レジストリパターンを利用
VENUE_REGISTRY = {
"マリンメッセ福岡": MarineMesseScraper,
"Zepp福岡": ZeppScraper
}
問題④ サーバーで Selenium が動かない
現在は Edge を起動して、実際にDOM操作を行えているかを確認しています。
webdriver.Edge()
ですが、Render や AWS などの Linux サーバーでは画面が存在しないため、このままいくと失敗するそうです。
解決策
ヘッドレスモードを利用します。
options.add_argument("--headless")
ChromeDriver を利用し、バックグラウンドで実行する。
最終的な構成
Next.js
↓ HTTP
FastAPI
↓
VenueScraper
↓
Selenium
↓
Gemini
学んだこと
- PythonスクリプトとWeb APIは別物
- FastAPIを使うとNext.jsから呼び出せる
- 抽象クラスで拡張性を確保できる
- レジストリパターンでif文地獄を防げる
- Seleniumは本番環境ではヘッドレス化が必須
今後やりたいこと
- FastAPI 化
- 会場スクレイパーの抽象化
- レジストリパターンの導入
- Render へのデプロイ
- Next.js との接続
