mcpField
S
scrape-codegen

scrape-codegen

github.com/zytedataデータ・データベース11174 回インストール2 日前に更新
リポジトリ

scrape-codegen について

抽出仕様と保存済み HTML をもとに、Scrapy プロジェクト向けの web-poet ページオブジェクトを生成し、テストする Claude スキルです。

主な機能

  1. 01ページオブジェクトの雛形生成
  2. 02保存済み HTML ページの分析
  3. 03スキーマに基づく抽出コード生成
  4. 04フィクスチャ変換とテスト実行

活用シーン

  1. 01抽出仕様からページオブジェクトを作成
  2. 02リストページの抽出コードを生成
  3. 03保存済みフィクスチャで抽出をテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/zytedata/skills --skill scrape-codegen

インストール後、Claude Code で/scrape-codegenを入力して読み込まれたか確認します。

同梱ファイルscripts/convert_fixtures.py

詳細

抽出仕様から web-poet ページオブジェクトを生成します。仕様には、スキーマ、保存済みの HTML ページ、期待される値が含まれています。商品詳細、ナビゲーションリンク、記事の内容など、どのようなデータ型も記述できます。Codegen はデータ型を把握する必要はありません。スキーマに従って抽出する PO を生成します。

仕様は /scrape-spec によって作成され、プロジェクトは /scrape-ensure-project によって作成されています。

${CLAUDE_SKILL_DIR}/../scrape/references から python-environments.md と docs-access.md を読みます。

入力

生の引数文字列は $ARGUMENTS です。空白で区切られた位置引数を最大 3 つに分割します。

  1. spec_path:仕様フォルダーのパス。例:.scrape/books-toscrape
  2. project_dir:Scrapy プロジェクトのパス
  3. fields:任意。生成するフィールド名をカンマ区切りで指定します(空の場合はすべてのフィールド)

処理

ステップ 1:仕様を読み取る

{spec_path}/spec.json を読み取り、以下を取得します。

  • schema.properties — フィールド定義
  • html_variant — 使用する HTML(raw または rendered)
  • url — 開始 URL(ドメイン名に使用)
  • data_type — 抽出対象(クラス名に使用)。常に単数形です(例:product、book)

次の規則に従って data_type から名前を導出します(複数形にはしません)。

  • ClassName = PascalCase + Page → product → ProductPage
  • ItemClass = PascalCase + Item → product → ProductItem
  • module_name = data_type の snake_case → product → product

fields が指定されている場合は、schema.properties をそのフィールドのみに絞り込みます。

{spec_path}/pages/ 内のページディレクトリのうち、{spec_path}/values/ に対応する値があるものを一覧表示します。それぞれの期待値を読み取ります。

spec_path から site_name を導出します(親ディレクトリ名。例:.scrape/books-toscrape/products から books-toscrape)。{project_dir} からプロジェクト名を特定します。

リスト型の判定。 data_type が -list で終わる場合(例:products-list):

  • is_list_type = true に設定します。
  • -list の接尾辞を取り除いて base_type を設定します(例:products)。
  • base_type の末尾に s がある場合は削除して単数形にし、その後 TitleCase にして ItemClass を導出します(例:products → product)。すでに単数形に見える場合は、そのまま TitleCase にします。
  • WrapperClass = {ItemClass}ListItems(例:ProductListItems)
  • PageClass = {ItemClass}ListPage(例:ProductListPage)
  • 値は配列形式です:{"url": ..., "values": [{...}, ...]}

それ以外の場合は is_list_type = false に設定し、ClassName を TitleCase(data_type) + "Page" として導出します。

ステップ 2:アイテムとページオブジェクトのスタブを追加する

リスト型でない場合(is_list_type = false):

{project_name}/items.py に data_type に一致する既存のアイテムクラスがあるか確認します。存在しない場合は、スキーマに基づいて作成します(すべてのフィールドは省略可能で、| None = None とします)。

親スキルが後続の処理を続けられるよう、サブエージェントでページオブジェクトのスタブを追加します。

Agent(description="add page object stub", prompt="/scrape-add-page-object {project_dir}/{project_name}/pages/{module_name}.py {ClassName} {domain} web_poet.WebPage {project_name}.items.{ItemClass}")

html_variant が rendered の場合は、web_poet.BrowserPage を使用します。

リスト型の場合(is_list_type = true):

items.py に 2 つのクラスが必要です。存在するか確認し、不足しているクラスを作成します。

  1. ベースアイテムクラス(ItemClass。例:Product)— フィールドの型をスキーマに合わせた @dataclass です。例:

    @dataclass
    class Product:
        title: str
        price: str | None = None
    
  2. ラッパークラス(WrapperClass。例:ProductListItems)— items フィールドを 1 つだけ持ち、その型は list[ItemClass] | None = None の @dataclass です。例:

    @dataclass
    class ProductListItems:
        items: list[Product] | None = None
    

次に、サブエージェントでページオブジェクトのスタブを追加します。デフォルト値を持つラッパーフィールドだけの場合でも @field スタブが生成されるよう、items を引数 6 として明示的に渡します。

Agent(description="add page object stub", prompt="/scrape-add-page-object {project_dir}/{project_name}/pages/{module_name}.py {PageClass} {domain} web_poet.WebPage {project_name}.items.{WrapperClass} items")
ステップ 3:フィクスチャを変換する

プロジェクト構造からフィクスチャクラスのパスを特定します(例: {project_name}.pages.{module_name}.{ClassName})。

uv run ${CLAUDE_SKILL_DIR}/scripts/convert_fixtures.py \
    {spec_path} {project_dir} {fixture_class_path}
ステップ 4:ページを分析する(並列実行)
mkdir -p .scrape/.work/{site_name}/codegen-analyze

値を指定して、ページごとに 1 つの Agent を起動し、並列実行できるようすべてを 1 つのメッセージにまとめます。各エージェントは、4 つすべての引数を指定して /scrape-codegen-analyze を実行します。

/scrape-codegen-analyze {spec_path}/pages/{page_id}/{html_variant}.html .scrape/.work/{site_name} {spec_path}/spec.json {spec_path}/values/{page_id}.json

HTML ファイルが存在しないページはスキップします。

リスト形式の仕様では、ページ名は list-* で、値には配列が含まれます。 scrape-codegen-analyze スキルは、meta.json(page_type が list)からリストページを自動検出し、コンテナーをベースとした抽出手順を生成します。

ステップ 5:ページオブジェクトのコードを生成する

すべての分析エージェントの完了後、3 つすべての引数を指定して /scrape-codegen-generate を実行する Agent を 1 つ起動します。

/scrape-codegen-generate .scrape/.work/{site_name} {project_dir}/{project_name}/pages/{module_name}.py {spec_path}/spec.json
ステップ 6:テストする
cd {project_dir} && uv run pytest fixtures/ -x -v

結果を報告します。テストに失敗した場合は、エラーを確認し、失敗したフィールドの再生成を検討します。

ステップ 7:報告する
Generated page object at {project_dir}/{project_name}/pages/{module_name}.py:
  Class: {ClassName} (N fields)
  Fixtures: N test cases
  Tests: N/N passing

コード生成のルール

${CLAUDE_SKILL_DIR}/../scrape/references/web-poet.md の web-poet リファレンスに従い、さらに以下を守ります。

  • コードはシンプルでドメイン汎用的なものにし、サンプルページに過剰適合させないでください
  • データがない場合は None を返します。空文字列、False、[] は決して返さないでください
  • ガード節を使い、属性にアクセスする前に None かどうかを確認してください
  • フィールドメソッドに docstring を追加しないでください
  • 汎用的な Exception を捕捉せず、具体的な例外のみを捕捉してください
  • 決定的な出力を優先し、セットは避けてください(必要に応じて、リストと重複排除を使用します)
  • 分析でフィールドの取得元が構造化データ(JSON-LD、microdata)と判明した場合は、extruct を使用してください。メタデータ形式は前の段階の extract_metadata.py の出力と一致するため、ページオブジェクトでも同じアクセスパターンを利用できます
  • ブラウザーのレスポンスが必要な場合は、基底クラスとして BrowserPage を使用してください

コメント