scrapewright について
scrapewrightは、開発者やエージェント向けに、ECカタログなどのページから構造化データを抽出します。既知のプラットフォームを判別し、独自ページ用の抽出器も一度作成してキャッシュし、繰り返し利用できます。
主な機能
- 01プラットフォーム判別と商品抽出
- 02抽出器のキャッシュと再利用
- 03カスタムフィールドスキーマ
- 04コマンドラインとCSV、XLSX、JSONL出力
- 05オプションのJavaScriptレンダリング
活用シーン
- 01ShopifyやWooCommerceの商品収集
- 02求人ページから指定項目を抽出
- 03商品カタログをスプレッドシート化
MCP 対応
MCPサーバーは、サイト判別、商品スクレイピング、ページ抽出、サイト巡回、学習済みサイトの一覧をツールとして提供します。ローカル実行とホスト型サービスへの接続に対応します。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://scrapewright.app/mcpclaude mcp add --transport http ozymandias-owens-2-scrapewright https://scrapewright.app/mcp{"mcpServers":{"ozymandias-owens-2-scrapewright":{"type":"http","url":"https://scrapewright.app/mcp"}}}Cursor で開く{"servers":{"ozymandias-owens-2-scrapewright":{"type":"http","url":"https://scrapewright.app/mcp"}}}VS Code で開く{"mcpServers":{"ozymandias-owens-2-scrapewright":{"type":"http","url":"https://scrapewright.app/mcp"}}}{"mcpServers":{"ozymandias-owens-2-scrapewright":{"serverUrl":"https://scrapewright.app/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
https://scrapewright.app/mcp認証が必要ツール
5| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい |
詳細
scrapewright
URLを渡すだけで、スクレイパーを生成します。
Eコマースカタログのスクレイピングは、大きく2つのケースに分かれます。きれいなJSONフィードを公開している既知のプラットフォーム(Shopify、WooCommerce)と、それ以外のケースです。後者はサイトごとにパーサーを手書きし、マークアップが変わるたびに書き直す必要がある独自のHTMLです。scrapewrightなら、どちらも1回の呼び出しにまとめられます。
- URLの背後にあるプラットフォームを検出します。
- 既知のプラットフォームでは、公開カタログAPIから決定論的に抽出します。無料で安定しており、LLMは不要です。
- 独自のHTMLでは、LLMで再利用可能な抽出器を一度合成してキャッシュし、その後はずっと決定論的に再実行します。
LLMは実行時の処理ではなく、コンパイラーです。サイトごとに一度だけ実行してCSSセレクターのレシピを生成し、それ以降のページはすべて通常のBeautifulSoupで解析するため、追加コストはかかりません。これがコスト管理の全てです。ページごとのモデル呼び出しも、クロール量に応じて増えるトークン料金もありません。
┌─────────────┐
store URL ───▶ │ detect │
└──────┬──────┘
┌──────────────────┼──────────────────┐
▼ ▼ ▼
shopify woocommerce generic HTML
products.json wc/store/products (page mode)
│ │ │
│ deterministic │ ▼
│ (free) │ cached recipe? ──yes──▶ replay (free)
└────────┬─────────┘ │ no
▼ ▼
Product{} ◀───── selectors ── JSON-LD? ──yes──▶ Product{} (free)
▲ │ no
│ ▼
└──────── replay ◀── LLM synthesizes recipe ONCE ──▶ cache
すべてのデータは共通のProduct形式に正規化されるため、後続のコードはレコードがどの経路で取得されたのかを知る必要も、気にする必要もありません。
インストール
pip install scrapewright # deterministic paths (Shopify, Woo, JSON-LD)
pip install "scrapewright[llm]" # + LLM recipe synthesis for custom HTML
pip install "scrapewright[llm,js,excel,mcp]" # + JS rendering, XLSX, MCP server
playwright install chromium # only needed for --js
使い方
from scrapewright import Scrapewright
sw = Scrapewright()
# Catalog mode — a whole Shopify/WooCommerce store, deterministically
for product in sw.scrape_catalog("https://shop.example.com", max_items=200):
print(product.brand, product.title, product.price, product.currency)
# Page mode — one custom-HTML product page.
# First call: tries JSON-LD (free); if absent, the LLM writes a recipe once.
# Every later call on that domain: replayed from the cached recipe, no LLM.
item = sw.scrape_page("https://boutique.example.com/products/wool-coat")
print(item.model_dump(exclude={"raw"}))
# Crawl mode — walk a WHOLE custom store from one listing/category URL.
# The frontier discovers product pages (deterministic, free); the first page
# pays the single synthesis cost, every other page replays the recipe.
for product in sw.crawl("https://boutique.example.com/collection", max_items=100):
print(product.title, product.price)
CLI
scrapewright detect https://shop.example.com # platform + strategy
scrapewright run https://shop.example.com --max 50 # scrape a catalog → JSONL
scrapewright crawl https://boutique.example.com/collection -o products.xlsx
scrapewright run https://shop.example.com -o products.csv # Excel-ready CSV
scrapewright add https://boutique.example.com/products/coat # learn a site
scrapewright run https://boutique.example.com/products/coat --no-llm
scrapewright list # cached recipe domains
-oを指定すると、.csv(Excel対応、UTF-8 BOM付き)、.xlsx(pip install scrapewright[excel])、または.jsonlに書き出します。指定しない場合、商品データはJSONLとして標準出力にストリーム出力されます。
対象を把握する
detectは、ジョブを開始する前にルーティング先を判定します。
$ scrapewright detect https://some-store.com
https://some-store.com
platform: bigcommerce
catalog: -
strategy: crawl
note: BigCommerce (Stencil) markup
12のプラットフォームを識別します。ShopifyとWooCommerceは無料のJSONカタログを公開しているため、catalogにルーティングされます。決定論的に処理され、LLMもブラウザーも不要です。Magento、BigCommerce、Salesforce Commerce Cloud、Squarespace、Wix、Webflow、PrestaShop、Shopware、Ecwid、OpenCartはフィンガープリントによって識別され、crawlにルーティングされます。レシピによる処理で、他の独自サイトと同様に扱われます。これらの名前を挙げているのは、12個のパーサーを書くためではなく、対象を把握するためです。WixとEcwidはクライアント側でレンダリングするため、検出時にあらかじめcrawl+jsと表示されます。
ボット対策の壁のあるサイトでは、何も見つからなかったかのように振る舞うのではなく、HTTPステータスとともにstrategy: blockedを報告します。
独自のスキーマを使う
商品データは組み込みのデフォルトにすぎません。必要なフィールドを宣言すれば、コンパイルは一度だけ、再実行は無料という同じ仕組みを、求人情報、掲載情報、登録記録など、構造化されたあらゆるページで利用できます。
scrapewright run https://jobs.example.com/p/123 -f title -f company -f salary:number -f tags:list --schema-name job
from scrapewright import Scrapewright, Schema
job = Schema.from_names(["title", "company", "salary:number", "tags:list"], name="job")
record = Scrapewright().extract("https://jobs.example.com/p/123", job)
print(record.data) # {'title': ..., 'company': ..., 'salary': ..., 'tags': [...]}
フィールドの種類はtext(デフォルト)、number、url、listです。numberフィールドは、ページ上の表記がどのような形式でも数値として解析します。"£51.77"、"1.250,00"、"€72,000"はすべて数値になります。ページに数字以外の情報も含まれていた場合、元の値は<field>_textとして併せて保持されます。
{ "price": 51.77, "price_text": "£51.77" }
数値をまったく含まない値(「お問い合わせください」など)は破棄せず、ページ上の表記のまま保持します。レシピはサイトごと、かつスキーマごとにキャッシュされるため、同じドメインを複数のフィールドセットに対してコンパイルしても、互いに上書きされません。
AI エージェントから使う(MCP)
scrapewright は MCP に対応しているため、エージェントは生の HTML を自分で読み取る代わりに、ツールとして呼び出せます。利用方法は 2 通りあります。
ホスト型。インストール不要です。 scrapewright.app で取得したキーを使って、クライアントをサービスに接続します(月 1,000 行まで無料。チャージしたことのないアカウントでは、1 日あたり新しいサイトを 1 件コンパイルし、20 ページをレンダリングできます)。
{
"mcpServers": {
"scrapewright": {
"url": "https://scrapewright.app/mcp",
"headers": { "X-API-Key": "sw_..." }
}
}
}
ツール:detect_site、extract_page、crawl_site、crawl_status、account。REST API と同じクレジット残高から支払います。独自のモデルキーは必要ありません。
ローカル。独自のモデルキーを使います。 サーバーをマシン上で実行します。
pip install "scrapewright[mcp,llm]"
scrapewright mcp
任意の MCP クライアントをそのコマンドに接続すると、エージェントは 5 つのツール(detect_site、scrape_catalog、extract_page、crawl_site、list_learned_sites)を利用できるようになります。
クライアントの設定に以下を追加してください。Claude Desktop、Cursor など、MCP に対応するクライアントで使えます。
{
"mcpServers": {
"scrapewright": {
"command": "uvx",
"args": ["--from", "scrapewright[mcp,llm]", "scrapewright", "mcp"],
"env": { "ANTHROPIC_API_KEY": "sk-ant-..." }
}
}
}
キーが必要なのは、既知のプラットフォームを使っていないサイトで、レシピを一度作成する必要がある場合だけです。Shopify と WooCommerce のストアではキーなしで動作します。
コスト効率こそが重要です。ページを自分で読むエージェントは、ページごとにモデルのトークンを消費し続けます。このツールではサイトごとに 1 回だけ費用が発生します。エージェントが 500 ページをクロールする場合、必要なのは 500 回ではなく 1 回の統合処理です。プラットフォーム上のストア(Shopify、WooCommerce)は一切費用がかかりません。
サービスとして実行する
キー、クォータ、使用量の計測、バックグラウンドジョブに対応した、HTTP API の基盤も同じです。
pip install "scrapewright[service,llm]"
scrapewright keys create --label alice --plan free
scrapewright serve --port 8000
curl -X POST localhost:8000/v1/extract -H "X-API-Key: sw_..." -H "Content-Type: application/json" -d '{"url": "https://shop.example.com/products/coat"}'
| エンドポイント | 目的 |
|---|---|
POST /v1/detect | プラットフォームと戦略の検出(低コスト) |
POST /v1/extract | 1 ページを構造化レコードに変換 |
POST /v1/crawl | サイト全体をクロールし、ジョブ ID を返す(クロールはリクエスト終了後も続行します) |
... mode | links は一覧ページから商品ページへたどります · rows は一覧ページ自体のカードを読み取ります · like は商品ページ 1 件から、それと同じ形式のすべてのページを取得します |
GET /v1/jobs/{id} | クロールの状態を確認 |
GET /v1/jobs/{id}/download?format=csv|xlsx|jsonl | 完了したクロールの結果をファイルとして取得 |
GET /v1/usage | このキーの使用量とプランの照合結果 |
API を使わない方法もあります。scrapewright.app/account に一覧ページの URL とフィールド一覧を入力すると、クロールが実行され、スプレッドシートが返されます。
サブスクリプションなしのプリペイドクレジット
実際に費用がかかるのは、新しいサイトのコンパイル、つまりページに対する LLM の 1 回の処理だけです。小さな商品ページでは $0.02、重いレンダリングが必要なページでは $0.15 と見積もられています。それ以降の処理はすべて BeautifulSoup で行われます。コンパイル済みサイトから 1 万件目のレコードを提供する費用は無料です。そのため、クレジットはこの 1 つの処理を基準に価格設定され、ほかの処理はすべて相対的な単位で表されます。
| アクション | クレジット |
|---|---|
| レコード 1 件の提供 | 1 |
| ブラウザーによるレンダリング 1 回 | 5 |
| 新しいサイトのコンパイル 1 件 | 300 |
ページ取得、detect | 無料 |
$ scrapewright plans
pack credits price $/credit margin
starter 10,000 $10 0.00100 80.0%
growth 50,000 $40 0.00080 75.0%
scale 250,000 $150 0.00060 66.7%
Free: 1,000 credits a month, resetting.
利益率はサイトのコンパイルを基準に測定します。費用が発生するのはこのステップだけだからです。価格を変更した結果、どのパックでも利益率が 60%を下回るとテストは失敗します。無料アカウントで発生する当社の費用は、無料クレジットをすべて最も高額なアクションに使ったとしても、月あたり最大 $0.20 です。
クレジットは残高カウンターではなく台帳です。付与と請求はすべて行として記録されるため、請求に異議があった場合は明細を一行ずつ再構成できます。また、決済 webhook が再送されても二重にクレジットが付与されません(付与には冪等性キーを使用します)。クレジットがなくなると、残高と対処方法を含む 402 が返されます。クロールは手元のクレジット数を上限とするため、残高を超過する代わりに、呼び出し元が支払える範囲でジョブが停止します。
scrapewright credits grant <key_id> --pack starter --idempotency <payment_id>
scrapewright credits balance <key_id>
決済の受け付け
Stripe は組み込み済みで、コードの変更ではなく環境変数によって有効化されます。
pip install "scrapewright[service,stripe]"
export STRIPE_SECRET_KEY=sk_test_... # absent -> nothing is for sale
export STRIPE_WEBHOOK_SECRET=whsec_... # absent -> webhooks are refused
scrapewright serve
| エンドポイント | 目的 |
|---|---|
GET /v1/credits/packs | 価格一覧。公開されており、キーは不要です |
POST /v1/credits/checkout | 購入を開始し、Stripe Checkout URL を返します |
POST /v1/webhooks/stripe | Stripe からの決済通知 |
Webhook エンドポイントに API キーは不要 です。呼び出し元は Stripe であり、署名が 認証情報そのもの です。未検証のエンドポイントは、URL を推測できた人なら誰でも無料でクレジットを発行できる状態になってしまいます。連携を支えるルールは 3 つあります。
- すべての署名を検証します。 署名シークレットが設定されていない場合、未検証のまま受け付けるのではなく、Webhook を全面的に拒否します。
- 通信で渡された金額を決して信用しません。 イベントにはパックが指定されています。そのパックのクレジット数は独自の価格一覧から照合するため、改ざんされたペイロードでは、支払った分だけが購入されるか、何も購入されません。
- Checkout セッションをキーにして、付与処理を冪等にします。 Stripe は配信を再試行し、1 件の決済から複数のイベント種別が発生することがあります。実際に決済された金額を識別するのはセッション ID です。
examples/stripe_smoke_test.py は、4242 カードを使用して Stripe のテストモードで一連の処理を実行します。他のプロバイダーも、scrapewright.service.billing の同じ 2 メソッドからなる BillingProvider プロトコルに接続できます。プロバイダーがなければ、サービスは無料で動作します。これはデモやセルフホスト可能なインスタンスに適したデフォルト設定です。
Docker:
docker build -t scrapewright . # static paths
docker build -t scrapewright --build-arg WITH_JS=1 . # + headless Chromium
docker run -p 8000:8000 -v sw-data:/data scrapewright
クライアント側でレンダリングされるストア
--js(または Scrapewright(js=True))を追加すると、カタログをブラウザーでレンダリングするページも抽出できるようになります。
scrapewright run https://spa-store.example.com/products/x --page --js
scrapewright crawl https://spa-store.example.com/shop --js -o products.xlsx
レンダリングは 意図的に最小限に抑えられています。まず静的フェッチを実行し、静的 HTML が空のクライアント側シェルである場合、またはその HTML からの抽出に失敗した場合にのみ、Chromium を起動します。レンダリング済み HTML から学習したレシピには needs_js のタグが付くため、そのサイトでの次回以降の実行では、無駄な静的フェッチをスキップします。ブラウザーの起動は 1 回の実行につき最大 1 回で、すべてのページで再利用されます。
Product の構造
url: str # canonical product URL
title: str
brand: str | None
price: Decimal | None # parsed from "1,250.00" / "1.250,00" / "€1290" alike
currency: str | None
available: bool | None
images: list[str] # absolute URLs
sizes: list[str]
description: str | None
sku: str | None
source_platform: str # shopify | woocommerce | json-ld | selector
タイトル、価格、URL を持つレコードは 使用可能 です。バリデーター(scrapewright.coverage)は、バッチ全体における使用可能なレコードの割合を報告します。この数値に基づいて、レシピをキャッシュする前に信頼できるかどうかを判断します。
各要素の連携方法
| モジュール | 役割 |
|---|---|
detect | プラットフォームのレジストリ:無料のカタログプローブに続いて 12 プラットフォームのフィンガープリントを照合し、使用するストラテジーを返します |
extract/shopify、extract/woocommerce | 決定論的なカタログ抽出器 |
extract/jsonld | <script type="application/ld+json"> から schema.org/Product を抽出します。無料で、一般的です |
extract/llm | HTML から SelectorRecipe を合成します。一度だけ行うコンパイル手順です |
extract/selectors | BeautifulSoup でレシピを再生する、決定論的なランタイムです |
schema | Schema/Field。抽出対象を宣言します。PRODUCT_SCHEMA は組み込みのデフォルトです |
service/ | FastAPI アプリ:API キー(ハッシュ化して保存)、レコードベースのクォータ、コスト計測、バックグラウンドのクロールジョブ、プラグイン可能な決済 |
service/credits | クレジットの価格、パック、無料利用枠 |
service/stripe_billing | Stripe Checkout と署名検証済み Webhook |
service/pricing | 実測した単価と各パックのマージン |
mcp_server | AI エージェントが scrapewright を直接呼び出せる 5 つの MCP ツール |
fetch | StaticFetcher(通常の HTTP)と BrowserFetcher(ヘッドレス Chromium)、およびレンダリングに費用をかける価値があるかを判断するシェルヒューリスティック |
crawl | フロンティア:1 つのリスト URL から商品 URL を生成します(パターンマッチ+カードテンプレートのフォールバック+ページネーション)。決定論的で、LLM は使いません |
cache | ドメインをキーにレシピを永続化し、コンパイルを 1 回で済ませます |
validate | フィールドカバレッジのスコアリング |
export | バッチから .csv / .xlsx / .jsonl へのエクスポート |
pipeline | detect → extract → validate → cache → heal をオーケストレーションします |
設計上のメモ
- 決定論的なパスを最初に実行します。 Shopify JSON、WooCommerce Store API、JSON-LD で、実際のストアの大部分を無料でカバーできます。LLM に到達するのは、本当にカスタム HTML が必要な場合だけです。
- 自己修復機能。 キャッシュされたレシピで有効な商品を取得できなくなった場合(サイトの DOM が変更された場合)、そのページは無料の JSON-LD パスにフォールバックし、それでも失敗した場合は新たに合成したレシピで古いレシピを置き換えます。サイトが壊れても、空のフィールドを黙って返すのではなく、次回の実行時に復旧します。
- モデル利用費の上限。 バッチ実行とクロール実行では、LLM の呼び出し回数を
max_synth_per_run(デフォルトは 3)に制限します。合成が難しいサイトがあっても、ページごとにモデルを呼び出すことにはなりません。クロールの規模にかかわらず、費用に上限を設けられます。 - プロバイダーを設定可能。 LLM 抽出器は
modelを受け取り、注入された任意のクライアントで動作します。デフォルトでは、公式 SDK を通じて Anthropic の Claude を対象とします。
テスト
決定論的なパスはオフラインのフィクスチャで完全にカバーされているため、ネットワークもモデル呼び出しも不要で、API キーがなくても CI は成功します。
pip install "scrapewright[dev]"
pytest
ステータス
v0.9(アルファ版)。実装・テスト済みの機能:API キー対応の HTTP サービス、前払いクレジット(費用がかかる唯一の操作に基づく料金設定と監査可能な台帳)、署名検証済み Webhook を備えた Stripe チェックアウト、コスト計測とバックグラウンドジョブ、12 のストアフロントに対応したプラットフォーム検出 (サイトごとに推奨戦略を提示)、カタログ抽出(Shopify、WooCommerce)、ページ抽出(JSON-LD、LLM が合成するセレクター)、レシピのキャッシュ、 モデル利用予算を実行ごとに制限した自己修復型の再合成、クロールフロンティア(1 つの一覧 URL からサイト全体を対象)、オプションの Playwright フェッチャーを使用した JS レンダリング と自動エスカレーション、スキーマに依存しない抽出 (フィールドを自由に指定可能)、AI エージェント向けの MCP サーバー、カバレッジ検証、CSV/XLSX/JSONL エクスポート。オフラインテスト 141 件。
既知の制限を明確に述べると、アンチボットの壁は突破しません。これは意図的に対象外としています。Akamai/Fastly 形式のチャレンジの背後にあるサイトでは、正直に取得失敗を返します。
ロードマップ:無限スクロール形式の一覧向けページネーション戦略、およびサービスのデプロイ済みインスタンス。
ライセンス
MIT — LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。