アクセラレーターシリーズ:LangGraphとTrueFoundryを用いたレジリエントなWebスクレイパーの構築

Built for Speed: ~10ms Latency, Even Under Load
Blazingly fast way to build, track and deploy your models!
- Handles 350+ RPS on just 1 vCPU — no tuning needed
- Production-ready with full enterprise support
営業チームはパニック状態です。来週、大規模なヘルスケアカンファレンスが開催されます。イベントのウェブサイトには、医師、役員、研究者など200人の講演者が、12以上のページ分割されたサブページにわたって掲載されています。リードリストを作成するには、誰かがサイトを開き、名前をクリックし、詳細をスプレッドシートにコピーし、新しいタブを開き、その人物をLinkedInで検索し、プロフィールURLをコピーして貼り付ける必要があります。
これを200回繰り返さなければなりません。

エンジニアにとって、この要求は通常、SeleniumやBeautifulSoupを使った簡単なPythonスクリプトになります。ページソースを検査し、speaker-nameクラスを持つdivを見つけてテキストを抽出します。約1週間は完璧に動作しますが、その後ウェブサイトがフロントエンドフレームワークを更新し、CSSクラスが変更されると、スクリプトはクラッシュしてしまいます。
私たちは プロフィールクローラー アクセラレーターを構築し、このサイクルを止めました。これは、HTMLの構造ではなく、ページに書かれている内容に基づいてウェブサイトをナビゲートし、データを抽出する自律型エージェントです。
オーケストレーションにLangGraph、インタラクションにPlaywright、インフラ管理にTrueFoundryを使用して、このソリューションをどのように設計したかをご紹介します。
転換点:DOMセレクターからセマンティック抽出へ
スクレイピングスクリプトが失敗する主な理由は、Document Object Model (DOM) への依存です。スクリプトにdiv.content-wrapper > h2.titleを探すように指示すると、開発者がクラス名を変更した瞬間に壊れてしまいます。
私たちはエージェントベースのアプローチに移行しました。ボットに どこに データがピクセル単位でどこにあるかを指示するのではなく、レンダリングされたHTML(Markdownに変換したもの)をLLMに供給します。モデルは人間と同じようにテキストを読み取ります。基盤となるタグに関係なく、「Keynote Speakers」とラベル付けされたセクションに目的のデータが含まれていることを理解します。
- 従来の方法(脆弱): UIの更新で壊れるハードコードされたCSSセレクター。
- 新しい方法(堅牢): レイアウトの変更に適応するセマンティックな理解。
アーキテクチャの詳細
私たちは、単なる線形スクリプトではなく、意思決定を処理できるシステムが必要でした。アプリケーションは以下を決定する必要があります。 この入力はURLですか、それとも単なる会社名ですか?キャプチャに引っかかりましたか?このページは人物リストですか、それとも単一の経歴ですか?
このワークフローをステートマシンとしてモデル化するためにLangGraphを選択しました。特に、 Langflow vs LangGraph ステートフルなオーケストレーションが有利な決定の場合です。
ロジックフロー
システムは直線的ではなく、ループで動作します。
- 入力ルーター: システムは、ユーザーが直接URLを提供したのか、それとも単なる会社名を提供したのかを確認します。会社名の場合、まず検索ツールを使用して正しいドメインを見つけます。
- ステルスナビゲーション: ページを読み込むために、変更されたPlaywrightインスタンスを使用します。これは、クッキー同意バナーや遅延読み込み画像を自動的に処理します。
- ベクトルフィルタリング(最適化): 単一のカンファレンスページには200ものナビゲーションリンクがある場合があります。それらすべてをLLMのコンテキストウィンドウに供給すると、処理が遅く、コストもかかります。そこで、私たちは FastEmbed を使用してリンクテキストを埋め込み、ローカルの Qdrant インスタンスにクエリを実行します。これにより、リストは「チーム」または「スピーカー」に関連する上位10個のリンクに絞り込まれます。
- 抽出: LLMはフィルタリングされたコンテンツを解析し、構造化されたエンティティ(名前、役割、会社)を抽出します。
- エンリッチメント: 最後に、抽出された名前をループ処理し、検索ツール(Tavily)を使用して、それぞれのLinkedInプロフィールを見つけます。
システムアーキテクチャは以下の通りです。

インフラストラクチャとTrueFoundryの統合
プロダクション環境でヘッドレスブラウザやLLMエージェントを稼働させると、Chromiumからのメモリリーク、LLM APIのレート制限、プロセス分離の必要性など、運用上の課題が生じます。
これをデプロイしました。 TrueFoundry これらの特定の制約に対処するため
1. AIゲートウェイ(可観測性&キャッシング)
このアプリケーションは、ナビゲーションの決定にLLMを多用しています。ガバナンスがなければ、コストは急速に膨れ上がります。すべてのモデル呼び出しを介してルーティングしています。 TrueFoundry AI Gateway。
- キャッシング: エージェントが同じサイトを2回スクレイピングした場合、ゲートウェイは抽出ステップのためにキャッシュされたLLM応答を提供します。これにより、レイテンシーとコストが大幅に削減されます。
- レート制限: 大規模なバッチジョブ中にAPIクォータが枯渇するのを防ぐため、ユーザーごとに厳格な制限を設定しています。
- フェイルオーバー: OpenAIでダウンタイムが発生した場合、ゲートウェイはクロールを失敗させることなく、AnthropicまたはAzure OpenAIに自動的にリクエストを再ルーティングします。
2. モデルコンテキストプロトコル(MCP)
アプリケーションは、を使用して構築しました。 Model Context Protocol (MCP). 「クローラー」は単なるPython関数ではなく、MCPサーバーです。これにより、ブラウザ環境をサンドボックス化できます。ブラウザがクラッシュしても(JavaScriptを多用するサイトでは頻繁に起こります)、メインのアプリケーションロジックが停止することはありません。
インフラストラクチャ図

比較:スクリプト vs エージェント
このアーキテクチャと標準的なPythonスクリプトのアプローチを比較評価しました。
エッジケースへの対応
ハッピーパスを構築するのは簡単です。しかし、それを信頼性の高いものにするには、3つの具体的なエンジニアリング課題を解決する必要がありました。
- 重複データ: プロフィールは複数のページ(例:「リーダーシップ」と「会社概要」の両方)に表示されることがよくあります。そこで、 重複排除ノード をグラフの最後に配置しました。これにより、完全なリストがより小さく安価なLLMに渡され、エンリッチメントの前に名前の類似性に基づいてレコードがマージされます。
- アンチボット検出: 標準のPlaywrightは、最新のWAFによって容易に検出されます。そこで、Dockerコンテナ内にundetected-playwrightを実装し、ブラウザのフィンガープリント(Navigatorオブジェクト、WebGLベンダー)をパッチして、標準的なユーザーデバイスとして認識されるようにしました。
- トークン制限: プライバシーポリシーやフッターを含む大きなページはトークンを浪費します。そこで、 ヘッダーベースのチャンキング を使用してマークダウンを分割します。LLMは「チーム」または「スピーカー」に関連するチャンクのみを処理し、残りは破棄します。
まとめ
このアーキテクチャは、脆弱なスクリプトを適応型エージェントに置き換えることで、データ取得の「ラストマイル」問題を解決します。TrueFoundry上で実行することで、システムが監視可能で、コストが管理され、スケーラブルであることを保証します。
この正確なアーキテクチャ(ゲートウェイ構成とDocker化されたエージェントを含む)は、TrueFoundryアプリケーションライブラリから今すぐデプロイできます。
TrueFoundry AI Gateway delivers ~3–4 ms latency, handles 350+ RPS on 1 vCPU, scales horizontally with ease, and is production-ready, while LiteLLM suffers from high latency, struggles beyond moderate RPS, lacks built-in scaling, and is best for light or prototype workloads.














.webp)
.webp)


.png)

.png)














