Webスクレイピングにおいて最もエンジニアを悩ませるのは、サイトのデザイン改修やCSSクラス名変更に伴う 「セレクターの定期メンテナンス」 です。
従来のスクレイピングは「DOMツリーを どのように(HOW) 探索するか」を記述するものでしたが、LLMを活用したアプローチでは「 何が(WHAT) 欲しいか」を定義するだけで抽出が可能になります。
本記事では、公式Python SDK「scraping-ai」を用いた内部アーキテクチャとデータパイプラインの仕組みを解説します。
内部パイプラインの4ステップ
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 1. スマート取得 │ ─────▶│ 2. Markdown変換 │ ─────▶│ 3. LLMスキーマ │
│ & 動的レンダリング │ │ (ノイズ除去) │ │ 照合・推論 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ 4. 検証済み │
│ 構造化JSON出力 │
└─────────────────┘
1. スマート取得と動的レンダリング
- 通常の静的ページは高速に取得します。
- React、Vue、Next.js等のSPAや動的コンテンツを検知した場合、自動的にクラウド上のヘッドレスブラウザ環境を起動してJavaScriptを実行・描画完了を待機します。
2. Markdownへのノイズ除去変換
生のHTMLには、インラインSVG、広告タグ、CSSスタイル定義などの膨大なノイズが含まれています。
抽出精度とトークン効率を高めるため、HTMLを意味構造を保持した軽量Markdownに変換します。
3. LLMによる意味的スキーマ照合(Semantic Matching)
GPT-4o / Geminiを用いて、指定されたJSON Schemaに基づきデータを抽出します。
CSSクラス名ではなく「文脈と意味」を理解して抽出するため、クラス名が難読化(._3xP9z)されても影響を受けません。
4. JSON Schemaバリデーション
LLMの出力結果を定義されたJSON Schemaで型検証(数値変換、真偽値判定等)し、クリーンな構造化データとしてPython SDKに返却します。
Python SDK(scraping-ai)での実装コード
まず、PyPIからSDKをインストールします。
pip install scraping-ai
1. 同期クライアント(ScrapingAIClient)
基本的なデータ抽出は、ScrapingAIClientを使用して実行できます。
from scraping_ai import ScrapingAIClient
# クライアント初期化
client = ScrapingAIClient(api_key="YOUR_API_KEY")
# URLとスキーマを指定して抽出
try:
data = client.extract(
url="https://example.com/products/wireless-headphones",
schema={
"title": "string",
"price": "number",
"in_stock": "boolean",
"rating": "number"
}
)
print(data.results)
except Exception as e:
print(f"抽出エラー: {e}")
ポイントは、CSSセレクターを直接指定するのではなく、取得したいデータのスキーマを定義することです。
例えば、以下のように定義します。
{
"title": "string",
"price": "number",
"in_stock": "boolean",
"rating": "number"
}
このように定義することで、ページ内から意味的に対応する情報を抽出します。
2. 非同期クライアント(AsyncScrapingAIClient)
大量のURLを並行処理したい場合は、非同期クライアントを使用します。
import asyncio
from scraping_ai import AsyncScrapingAIClient
async def scrape_product(url: str):
async with AsyncScrapingAIClient(api_key="YOUR_API_KEY") as client:
result = await client.extract(
url=url,
schema={
"title": "string",
"price": "number",
"in_stock": "boolean"
}
)
return result.results
async def main():
urls = [
"https://example.com/products/item-1",
"https://example.com/products/item-2"
]
tasks = [scrape_product(url) for url in urls]
results = await asyncio.gather(*tasks)
print(results)
if __name__ == "__main__":
asyncio.run(main())
このように asyncio.gather() と組み合わせることで、複数URLに対する抽出処理を並行して実行できます。
応用:LangChain / AIエージェントのツールとしての活用
抽出結果が厳格に型付けされたJSONで返却されるため、LangChainのToolとしてAIエージェントにWeb情報収集能力を付与することも容易です。
例えば、商品情報を取得するToolを以下のように定義できます。
from langchain.tools import tool
from scraping_ai import ScrapingAIClient
client = ScrapingAIClient(api_key="YOUR_API_KEY")
@tool
def fetch_web_product_info(url: str) -> dict:
"""指定URLから商品名、価格、在庫状況を構造化JSONとして抽出するツール"""
result = client.extract(
url=url,
schema={
"title": "string",
"price": "number",
"in_stock": "boolean"
}
)
return result.results
これにより、AIエージェント側からURLを渡すだけで、Webページの商品情報を構造化データとして取得できます。
制約事項と使い分け
LLMを利用したスクレイピングは便利ですが、すべてのケースで従来型のスクレイピングより優れているわけではありません。
BeautifulSoupが適しているケース
- 単発の学習スクリプト
- 構造が変わらない社内イントラサイト
- 完全無料で運用したい場合
Scraping AIが適しているケース
- 本番運用のデータ収集パイプライン
- 複数ECサイトの定期的な価格監視
- Webサイトの変更によるセレクター改修工数を削減したい場合
制限事項
- SNS(X / Instagram等)のスクレイピングは規約上非対応です。
- 極めて厳格なアンチボット(Cloudflare Turnstile等)に対する自動ステルス回避率は約85%です。
そのため、従来型のスクレイピングとLLMベースのスクレイピングは、用途に応じて使い分けることが重要です。
無料で試す(200トークン付与)
Scraping AIは無料アカウントから試すことができます。
-
無料アカウント登録(クレジットカード不要)
https://pig-data.jp/service/scraping-ai/ -
PyPIパッケージ
https://pypi.org/project/scraping-ai/
運営企業・チームについて
Scraping AIは、株式会社SMSデータテックのAIベンチャー子会社である indigodata株式会社 が開発・運営しています。
国内500件以上の受託データ収集実績を持つ「PigData」の知見をベースに、開発者向けセルフサーブ型LLMスクレイピングAPIを提供しています。
詳しくは以下をご覧ください。
まとめ
従来のWebスクレイピングでは、HTML構造やCSSセレクターに依存するため、サイト側のデザイン変更やクラス名変更が発生するたびにコードのメンテナンスが必要でした。
LLMを活用したスクレイピングでは、
- Webページを取得
- HTMLをMarkdownへ変換してノイズを除去
- LLMで指定したスキーマとページ内容を意味的に照合
- JSON Schemaで検証
- 構造化データとして取得
というパイプラインによって、「どの要素を取得するか」ではなく「何のデータが欲しいか」 を定義したスクレイピングが可能になります。
特に、複数サイトから継続的にデータを収集するシステムでは、セレクターの保守コストを削減できる可能性があります。
一方で、単純かつ安定したHTMLを対象とする場合は、BeautifulSoupなどの従来型スクレイピングのほうがシンプルで低コストです。
用途に応じて、従来型スクレイピングとLLMベースのスクレイピングを使い分けるのが現実的なアプローチと言えるでしょう。