scrape-spec について
scrape-specは、Webサイトの抽出仕様を拡張・検証するスキルです。詳細ページや一覧ページをサンプリングし、HTMLの種類を比較して、抽出値とナビゲーションデータを作成します。
主な機能
- 01詳細ページと一覧ページのサンプル取得
- 02rawとrenderedのHTMLを比較
- 03仕様フィールドの抽出値を検証
- 04ナビゲーションデータ型を作成
活用シーン
- 01初期のサイト仕様の拡張
- 02ページ形式ごとの抽出結果の確認
- 03サンプルページからのナビゲーション値生成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zytedata/ skills --skill scrape-specインストール後、Claude Code で/scrape-specを入力して読み込まれたか確認します。
詳細
/scrape-define で作成した抽出仕様を拡張し、検証します。さまざまな詳細ページと一覧ページをダウンロードして、HTML のバリエーションを比較し、値を抽出します。必要に応じて、ブラウザーで確認できる形で提示します。
${CLAUDE_SKILL_DIR}/../scrape/references/python-environments.md を読みます。
入力は、少なくとも 1 つのデータ型(スキーマと 1 ページを含む)がある仕様フォルダーです(/scrape-define で作成)。出力は、ページ、検証済みの値、ナビゲーションデータ型を追加した同じフォルダーです。
入力
生の引数文字列は $ARGUMENTS です。これはそのまま使用する単一の値です。
- site_path:サイト仕様フォルダーのパス。例:
.scrape/books-toscrape
ステップ 1:既存の仕様を読む
{site_path}/spec.json を読み、url と data_types を取得します。
主要なデータ型(data_types のうち、最初に見つかる "navigation" 以外のデータ型)について、次を読みます。
{site_path}/{data_type}/spec.json→schema、html_variant
site_path の最後の要素から site_name を導出します。例:books-toscrape
ステップ 2:サイトを調査する
ステージ 1 ではページを保存せず、スキーマと値のみを保存します。ステージ 2 では、サブエージェント内で /scrape-explore-site を使用して、新しいページを少数ダウンロードします。
Agent(description="explore-site", prompt="Run /scrape-explore-site {url} .scrape/.work/{site_name}/explore 2 2")
これにより、開始ページ、最大 2 件の詳細ページ、最大 2 件の一覧ページがダウンロードされ、リンクが分類され、ナビゲーションの値が生成されます。出力はすべて .scrape/.work/{site_name}/explore/ に保存されます。
サブエージェントからサイトがブロックされていると報告された場合は、/scrape-zyte-login を実行します。完了後、上記の scrape-explore-site サブエージェントを再実行します。調査が成功するまで先に進まないでください。
その後、ページを適切なデータ型のサブフォルダーに振り分けます。
mkdir -p {site_path}/{data_type}/pages {site_path}/navigation/pages {site_path}/navigation/values
# Detail pages → data type
for d in .scrape/.work/{site_name}/explore/pages/detail-*; do
[ -d "$d" ] && cp -r "$d" {site_path}/{data_type}/pages/
done
# Start + list pages → navigation
for d in .scrape/.work/{site_name}/explore/pages/start-* .scrape/.work/{site_name}/explore/pages/list-*; do
[ -d "$d" ] && cp -r "$d" {site_path}/navigation/pages/
done
# Navigation values (generated by explore-site)
cp .scrape/.work/{site_name}/explore/values/*.json {site_path}/navigation/values/ 2>/dev/null || true
ステップ 3:ナビゲーションの HTML バリエーションを判定する
詳細ページを分析する前に、ナビゲーションページに必要な HTML バリエーションを個別に判定します。すべてのナビゲーションページに対して、両方のバリエーションを使用して extract_links.py を実行します。
mkdir -p .scrape/.work/{site_name}/analyze-nav
uv run ${CLAUDE_SKILL_DIR}/../scrape-explore-site/scripts/extract_links.py \
{site_path}/navigation/pages/*/raw.html \
--group --base-url-from-meta \
> .scrape/.work/{site_name}/analyze-nav/nav.raw.json 2>/dev/null || true
uv run ${CLAUDE_SKILL_DIR}/../scrape-explore-site/scripts/extract_links.py \
{site_path}/navigation/pages/*/rendered.html \
--group --base-url-from-meta \
> .scrape/.work/{site_name}/analyze-nav/nav.rendered.json 2>/dev/null || true
両方の出力ファイルを読み、リンクのグループを分析します。グループ構造、各バリエーションに有用なナビゲーションリンクがあるかどうか、一方のバリエーションで他方が見落とすリンクが見つかるかどうかを考慮して、どちらの HTML バリエーションがナビゲーションをよりよく網羅しているかを判定します。レンダリング済みのバリエーションがナビゲーションを明らかに大幅に網羅できる証拠がない限り、raw を優先してください。
ステップ 6 で使用するため、結果を nav_html_variant として保存します。
ステップ 4:詳細ページのサンプルと一覧ページを並行して分析する
まず、両方の HTML バリアントがある詳細ページのサンプルを絞って分析します。一覧ページがある場合は、raw.html と rendered.html の両方がある最初の詳細ページを使用します。一覧ページがない場合は、最初の 1~2 件の詳細ページを使用します。つまり、詳細ページのバリアント比較に使用するページ数は、一覧ページも分析する場合は最大 1 件、一覧ページがない場合は最大 2 件です。バリアント比較のために、詳細ページ分析エージェントを 4 つより多く起動しないでください。これにより、ワークフローの応答性を保ちつつ、raw または rendered のどちらから承認済みスキーマのフィールドを抽出できるかを検証できます。
また、データ型スキーマを使用して、{site_path}/navigation/pages/ のすべての一覧ページを raw バリアントで分析します。詳細サンプルのエージェントに加え、一覧ページごとに 1 つの Agent を、並列実行のため単一のメッセージで起動します。プロバイダーのスレッド数制限を超えないよう、起動する Agent の合計は 5 つ以下にします。一覧ページがある場合は、2 件目の詳細ページを分析するよりも、detail-1 の raw/rendered と一覧ページのエージェントを優先してください。すべての Agent 呼び出しは、間にツール呼び出しを挟まず、1 回の応答ですべて実行してください。残りのエージェントを起動する前に結果を待たないでください。
エージェントを起動する前に、出力ディレクトリを作成します。
mkdir -p .scrape/.work/{site_name}/analyze-page
mkdir -p {site_path}/{data_type}-list/values
Agent(description="analyze detail-1 raw", prompt="/scrape-analyze-page Extract data from {site_path}/{data_type}/pages/detail-1/raw.html using the schema in {site_path}/{data_type}/spec.json and save it into .scrape/.work/{site_name}/analyze-page/detail-1.raw.json ")
Agent(description="analyze detail-1 rendered", prompt="Run /scrape-analyze-page {site_path}/{data_type}/pages/detail-1/rendered.html using the schema in {site_path}/{data_type}/spec.json and save it into .scrape/.work/{site_name}/analyze-page/detail-1.rendered.json")
Agent(description="analyze list-1", prompt="/scrape-analyze-page --list-mode Extract all {data_type} items from {site_path}/navigation/pages/list-1/raw.html using the schema in {site_path}/{data_type}/spec.json and save it into {site_path}/{data_type}-list/values/list-1.json")
Agent(description="analyze list-2", prompt="/scrape-analyze-page --list-mode Extract all {data_type} items from {site_path}/navigation/pages/list-2/raw.html using the schema in {site_path}/{data_type}/spec.json and save it into {site_path}/{data_type}-list/values/list-2.json")
... (all list pages in the same message)
If there are no list pages, add the second detail-page pair instead:
Agent(description="analyze detail-2 raw", prompt="Run /scrape-analyze-page {site_path}/{data_type}/pages/detail-2/raw.html using the schema in {site_path}/{data_type}/spec.json and save it into .scrape/.work/{site_name}/analyze-page/detail-2.raw.json")
Agent(description="analyze detail-2 rendered", prompt="Run /scrape-analyze-page {site_path}/{data_type}/pages/detail-2/rendered.html using the schema in {site_path}/{data_type}/spec.json and save it into .scrape/.work/{site_name}/analyze-page/detail-2.rendered.json")
HTML ファイルが存在しないバリアントはスキップします。{site_path}/navigation/pages/ に一覧ページがない場合は、一覧ページのエージェントと {data_type}-list/values の mkdir をスキップします。schema_path は、承認済みのフィールド名、説明、例を analyze-page に渡すため、正しい名前と値の形式で抽出できます。ステップ 5 でバリアントを選択した後は、追加の詳細ページ分析を起動しないでください。すべての一覧ページエージェントの完了を待つ必要はありません。絞り込んだ詳細サンプルが完了し、少なくとも 1 つの一覧ページの values ファイルが利用可能になったら、完了済みの一覧ページ出力を使ってステップ 4.5 に進みます。これにより、任意の一覧ページ分析の遅延で最終処理が妨げられることはありません。
ステップ 4.5:一覧ページのデータ型を作成するか判断する
このステップは、ステップ 4 で一覧ページが見つかり、分析された場合にのみ実行します。
完了済みの {site_path}/{data_type}-list/values/list-*.json ファイルを読み込みます。各完了済みファイルについて、スキーマの source: "requested" フィールドがすべて、values 配列内の少なくとも 1 つの項目のキーとして存在するか確認します。一覧ページの values ファイルがまだ完了していない場合は、list_spec_created = false に設定し、待たずに詳細ページの抽出に進みます。
完了済みのすべての一覧ページ values ファイルで、要求されたフィールドがすべて見つかった場合:
list_spec_created = true に設定します。
-
{site_path}/{data_type}-list/spec.jsonを書き込みます:{ "url": "{url}", "data_type": "{data_type}-list", "html_variant": "raw", "schema": {<same schema object as in {site_path}/{data_type}/spec.json>} } -
一覧ページを新しいデータ型にコピーします:
mkdir -p {site_path}/{data_type}-list/pages for d in {site_path}/navigation/pages/list-*; do [ -d "$d" ] && cp -r "$d" {site_path}/{data_type}-list/pages/ done
それ以外の場合: list_spec_created = false に設定します。通常どおり詳細ページの抽出に進みます。{data_type}-list/values/ ディレクトリが残っていても、無視されます。
ステップ 5:HTML のバリアントを選択する
.scrape/.work/{site_name}/analyze-page/ の範囲を限定したサンプルで、raw と rendered の結果を比較します。
各ページについて、{page_id}.raw.json と {page_id}.rendered.json を比較します。
- どちらのバリアントがスキーマフィールドをより多く検出しましたか?
- どのフィールドが一方のバリアントでのみ見つかりましたか?
- 同じフィールドの値はバリアント間で異なりますか?
この比較には単一の小さな Python スクリプトを使用します。スクリプトは {site_path}/{data_type}/spec.json を読み込み、.scrape/.work/{site_name}/analyze-page/*.json を列挙し、スキーマフィールドの網羅状況と値のみを比較して、簡潔な概要を出力します。また、rendered が raw では見つからない要求対象のスキーマフィールドを一貫して検出する場合を除き、raw を推奨します。
デフォルトでは raw を優先します。raw はより高速で、低コストかつ信頼性が高いためです。rendered を使用するのは、raw では一貫して見つからないスキーマフィールドが検出される場合、または raw HTML が実質的に空の場合(SPA サイト)のみです。
比較結果をターミナルに表示します。
HTML variant comparison:
Both variants found: name, price, brand, description, image_url
Only in rendered: reviews_count (3/3 pages), sale_price (2/3 pages)
Only in raw: (none)
Value differences:
price: raw="$29.99", rendered="$24.99" (detail-1) — rendered may show sale price
Recommendation: raw (all schema fields found)
Note: rendered also has reviews_count, sale_price — say "use rendered" if you need these.
どちらのバリアントを使うべきか明確な場合は、そのバリアントを使用します。明確でない場合、たとえば raw ビューにフィールドの大半は含まれているものの、すべては含まれていない場合は、AskUserQuestion を使ってユーザーにどちらのバリアントを使用するか尋ね、詳細を提示します。
- question: "抽出にはどちらの HTML バリアントを使用しますか?"
- header: "HTML バリアント"
- options: "Use raw" と "Use rendered"。推奨するものに推奨マークを付けます。
この場合は、ユーザーが選択したバリアントを使用します。
範囲を限定したサンプルで両方のバリアントが承認済みのスキーマフィールドをすべて検出した場合は、すぐに raw を選択します。バリアントがステージ 1 で使用したものから変わる場合は、{site_path}/{data_type}/spec.json の html_variant を新しい値に更新します。バリアントを選択したら、そのままステップ 6 に進みます。分析エージェントを追加で起動しないでください。
ステップ 6:値を抽出する(list_spec_created が true の場合はスキップ)
list_spec_created が true の場合は、このステップをスキップします。値はステップ 4 で既に {data_type}-list/values/ に書き込まれています。
そうでない場合は、extract_values.py を使って、スキーマでフィルタリングした分析ファイルから値を生成します。
uv run ${CLAUDE_SKILL_DIR}/../scrape-explore-site/scripts/extract_values.py \
.scrape/.work/{site_name}/analyze-page/ \
{site_path}/{data_type}/spec.json \
--variant {html_variant} \
-O {site_path}/{data_type}/values/
これにより、既存の値ファイル(ステージ 1 で作成したものを含む)はすべて、分析済みの詳細ページサンプルから新たに抽出した値で上書きされます。--renames は不要です。ステージ 2 の analyze-page にはスキーマ全体(名前、説明、例)が渡されるため、正しいフィールド名で直接抽出できます。
ナビゲーション
${CLAUDE_SKILL_DIR}/../scrape/references/extraction-spec.md の固定ナビゲーションスキーマを使い、サイト URL と nav_html_variant(ステップ 3 で決定)を指定して、{site_path}/navigation/spec.json を作成します。
ナビゲーションの値は、ステップ 2 で explore-site の出力から既にコピーされています。
ステップ 7:任意のブラウザレビュー
まず抽出統計(「{N} 件の詳細ページと {M} 件のナビゲーションページの値を抽出しました。」)をユーザーに伝え、その後、ブラウザレビューを希望するか AskUserQuestion で尋ねます。
環境上、追加の質問ができない場合は、ブラウザレビューをスキップして続行します。
- question: "抽出した値をブラウザで確認しますか?"
- header: "ブラウザレビュー"
- options:
Skip browser review— "ブラウザを開かずに続行します。"Open browser review— "ブラウザで値を確認します。"
ユーザーが Skip review を選択した場合は、ステップ 9 に進みます。
ユーザーが Open browser review を選択した場合は、データ型の spec を指定して /scrape-review-schema を呼び出します。
/scrape-review-schema {site_path}/{data_type} .scrape/.work/{site_name} {schema_json} {html_variant}
ブラウザを開く前に、レビュー用ディレクトリのパスをユーザーに伝えます。
ステップ 8:フィードバックを適用する
ユーザーがレビューしてフィードバックを提供した場合:
フィードバックが APPROVED で始まる場合:含まれているスキーマの変更(フィールドの削除、名前の変更、説明の編集、保持するフィールド → ソースを "requested" に変更)を適用し、ステップ 9 に進みます。ユーザーの承認を得ています。
フィードバックが APPROVED で始まらない場合(ユーザーが「変更をリクエスト」をクリックした場合):
- スキーマの変更(フィールドの削除、名前の変更、説明の編集)を直接適用します
- 値の修正については、まずもう一方のバリアントの分析ファイルを確認します。もう一方のバリアントに正しい値がある場合は、バリアントの切り替えを提案します:
ユーザーが同意した場合は、バリアントを切り替え、仕様を更新して、値を再生成します。You corrected price to "$24.99" — the rendered variant already extracts this correctly (across 3/3 pages). Switch to rendered? [Y/n] - もう一方のバリアントで解決しない場合:選択したバリアントを使って、すべての詳細ページで修正対象フィールドの分析を再実行します。ページごとに 1 つずつ Agent を起動し、並行して実行します。
分析の再実行またはバリアントの切り替え後、値を再抽出し(ステップ 6)、再度レビューを依頼します。/scrape-review-schema の 5 番目の引数として変更の概要を渡します:
/scrape-review-schema {site_path}/{data_type} .scrape/.work/{site_name} {schema_json} {html_variant} '["Re-analyzed price across all pages","Dropped field isbn"]'
ユーザーがレビューを承認するかスキップするまで、ステップ 7~8 を繰り返します。
ステップ 9:確定する
レビューでスキーマに変更があった場合は、{site_path}/{data_type}/spec.json を更新します(詳細ページを使用した場合に限り該当します。list_spec_created が false の場合のみ)。
{site_path}/spec.json を更新し、data_types を次のように設定します:
list_spec_createdが true の場合:["{data_type}-list", "navigation"]— 詳細ページからの抽出は不要なため、"{data_type}"は省略します。- それ以外の場合:
["{data_type}", "navigation"]
報告:
list_spec_created が true の場合:
Spec finalized at {site_path}/:
{data_type}-list: {N} list pages, {F} fields, {K} items extracted
navigation: {M} pages
All requested fields found on list pages — skipping detail-page extraction.
Ready for codegen: /scrape-codegen {site_path}/{data_type}-list ./{project_dir}
それ以外の場合:
Spec finalized at {site_path}/:
{data_type}: {N} detail pages, {F} fields
navigation: {M} pages
Ready for codegen: /scrape-codegen {site_path}/{data_type} ./{project_dir}