mcpField
S
scrapy-extra

scrapy-extra

github.com/zytedata開発1157 回インストール2 日前に更新
リポジトリ

scrapy-extra について

scrapy-extraは、スパイダー、ページオブジェクト、アイテム、パイプライン、設定を実装・変更する開発者向けのScrapyスキルです。作業に応じた実装・テスト手順を示し、新規プロジェクトでは適切な場合にweb-poetのページオブジェクトを推奨します。

主な機能

  1. 01Scrapyの各コンポーネントの作成とデバッグ
  2. 02適切な新規スパイダーでweb-poetページオブジェクトを利用
  3. 03作業に応じたScrapyリファレンスを参照
  4. 04フィクスチャによるページオブジェクトのテスト
  5. 05件数を制限したクロールとアイテム確認

活用シーン

  1. 01Scrapyプロジェクトやスパイダーの作成
  2. 02既存クローラーの抽出処理の変更
  3. 03保存済みページのフィクスチャでページオブジェクトをテスト
  4. 04クロール出力の欠損フィールドや誤値の調査

インストール

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

$npx skills add https://github.com/zytedata/skills --skill scrapy-extra

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/project-template/
cookiecutter.json
assets/project-template/{{cookiecutter.project_name}}/
pyproject.toml
scrapy.cfg
assets/project-template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/
__init__.py
items.py
settings.py
assets/project-template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/pages/
__init__.py
assets/project-template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/spiders/
__init__.py
assets/project-template/{{cookiecutter.project_name}}/fixtures/
.gitkeep
references/
scrapy-poet.md
scrapy-zyte-api.md
scrapy.md
web-poet.md

詳細

このファイルは172行あります。すべて読んでください。

以下のSKILL_DIRは、このファイルを含むディレクトリの絶対パスを表します。

Scrapyのコーディングを実際に行います。スパイダー、ページオブジェクト、アイテム、パイプライン、設定、またはプロジェクト全体を作成・変更します。

新しいスパイダーでは、web-poetのページオブジェクトを優先してください。抽出処理を分離すると、スパイダーをクロールに集中させられ、保守、テスト、再利用も容易になります。どこまで導入するかはプロジェクトによって異なります。

  • 新規プロジェクト、またはすでにscrapy-poetを設定済みのプロジェクト:特に指示がなければ、ページオブジェクトを使用します。
  • スパイダーはあるものの、scrapy-poetを使用していない既存プロジェクト:ユーザーが導入を望まないと明言していない限り、scrapy-poetのサポート追加を提案し、勝手に導入することは避けます。代替策として、辞書やアイテムを返す通常のスパイダーを使用します。

依頼されていない限り、既存のスパイダーをページオブジェクトに移行したり、使用していないプロジェクトにweb-poetを追加したりしないでください。

Scrapyがすでに行う処理を再実装しないでください。重複リクエストは重複フィルターが自動的に除外するため、スパイダーに既処理URLの集合は不要です。

決まったワークフローも、必須の入力や出力もありません。タスクを読み、以下の関連リファレンスを確認して、慣用的なコードを書いてください。

リファレンス

SKILL_DIR/references/に含まれています。これから書く内容に応じて必要なものだけを読みます。多くのタスクで必要なのは1つです。

  • スパイダー、アイテム、パイプライン、セレクター、フィードエクスポート、または設定の作成・デバッグ → scrapy.md。
  • ページオブジェクトの作成・デバッグ、またはフィクスチャの保存・実行 → web-poet.md。
  • ページオブジェクトまたはアイテムをパラメーターとして受け取るスパイダーコールバック(handle_urls、DummyResponse、SCRAPY_POET_DISCOVER)の作成 → scrapy-poet.md。どちらを注入するかによってコールバックの形が決まります。
  • サイトがリクエストをブロックする場合やJavaScriptが必要な場合 → scrapy-zyte-api.md。

これ以外については、推測せず公式ドキュメントを取得してください。docs.scrapy.org、web-poet.readthedocs.io、scrapy-poet.readthedocs.io、scrapy-zyte-api.readthedocs.io、docs.zyte.comを参照してください。これらはLLM向けに配慮されています。URLの.htmlを.mdに置き換えるとMarkdownを取得でき、目次は<host>/llms.txtで確認できます。

環境

Pythonの実行にはすべてuvを使用してください。pythonやpipを直接実行してはいけません。uvがなければインストールしてください。

cd PROJECT_DIR && uv run scrapy crawl <name>
cd PROJECT_DIR && uv run --with pytest python -m pytest fixtures/

pytestコマンドを使うのは、プロジェクトにfixtures/ディレクトリがある場合です。ない場合は実行するものがありません。

.venv/、uv.lock、*.egg-info、build/は一時ファイルではなく、想定されているプロジェクトの状態です。そのまま残してください。実行時に生成される.pytest_cache/、__pycache__/、テストクロールのitems.jsonlも同様です。これらを探して削除しようとしないでください。

プロジェクトの作成

新規プロジェクトが必要なタスクの場合に限ります。同梱のテンプレートを使用してください。テンプレートにはscrapy-poetとZyte APIアドオンを設定済みのsettings.pyに加え、pages/、spiders/、fixtures/ディレクトリが含まれています。

uvx cookiecutter --no-input SKILL_DIR/assets/project-template \
    -o PARENT_DIR project_name=PROJECT_NAME
cd PARENT_DIR/PROJECT_NAME && uv sync

既存のプロジェクトでは、そのプロジェクト内で作業してください。必要な依存関係がpyproject.tomlにない場合は、不足しているものをユーザーに伝え、追加する前に確認してください。黙ってプロジェクトを書き換えてはいけません。

抽出コードの記述

スパイダーのコールバックでも、ページオブジェクトの @field でも、既知の他のプロジェクトガイドラインと矛盾しない限り、デフォルトで次のガイドラインに従ってください。

  • シンプルで、特定のドメインに依存しない方法にしてください。確認した特定のページに過剰適合させないでください(タイトルのハードコードや、ページごとの if/else は避けてください)。
  • サンプルページが複数ある場合は、最初のページだけでなくすべてのページで抽出結果を確認してください。たまたま開いたページでしか機能しないセレクターは過剰適合です。ページ間で結果が異なる場合は、より汎用的なセレクターを優先するか、フォールバックを使ってください(例:まず JSON-LD を使い、次に CSS を使う)。
  • データがない場合は "" や False ではなく、None を返してください。
  • 属性にアクセスする前にガードし、None かどうかを確認してください。
  • 裸の Exception を捕捉しないでください。予期される特定の例外だけを捕捉してください。例外は、リスト項目を反復処理する際の項目ごとの抽出です。この場合は、1 つの項目のエラーで残りの処理が止まらないよう、各項目の処理を Exception で囲んで捕捉し、exc_info=True を指定してログに記録してください(web-poet.md → Nested item extraction を参照)。
  • 決定論的な出力を優先してください(セットは避け、必要に応じてリストの重複を除去してください)。
  • 構造化データがある場合は、それを優先してください。JSON-LD/microdata/OpenGraph には extruct、JSON クエリには jmespath、価格には price_parser を使ってください。
  • データに JavaScript が必要な場合に限り、ブラウザーでのレンダリングを要求してください。ページオブジェクトを使う場合は、ページオブジェクトの入力としてその要件を宣言してください。つまり、BrowserPage をサブクラス化して BrowserResponse に依存させてください。automap のパラメーターや custom_settings を通じて browserHtml を有効にしないでください。ページオブジェクトを使わない場合は、必要なリクエストに限り、リクエストごとに meta={"zyte_api_automap": {"browserHtml": True}} を指定してください(scrapy-zyte-api.md を参照)。

抽出処理は抽出を行い、フィルタリングは行いません。 値による結果の除外や制限をユーザーから求められた場合でも、そのロジックをページオブジェクトや抽出メソッドに入れないでください。フィルタリング、重複除去、検証はスパイダーまたはアイテムパイプラインで行います。プロジェクトにまだどちらもない場合は、フィルターをページオブジェクトに移すのではなく、フィルター自体を追加しないでください。リクエストがこれに反する内容を示唆していた場合は、概要でその旨を伝えてください。

テスト

  • ページオブジェクト:セレクターを個別にテストするのではなく、to_item() を実行して期待値と比較し、検証します。@field メソッド、Returns、出力処理によって、生のセレクター値が最終的なフィールドに変換されるためです。pytest で検証する web-poet のフィクスチャとして作成してください。実際のページオブジェクトを実行し、HttpResponse と BrowserResponse のどちらのページでも同じように動作し、回帰テストとして残ります。手元にある入力を使ってフィクスチャを作成します。

    • ライブ URL → uv run scrapy savefixture <page.object.ClassPath> '<url>'。
    • 保存済みのサンプル HTML のみ(URL なし)→ 各ファイルから入力を作成し、web_poet.testing.Fixture.save でフィクスチャを保存します(コード例は web-poet.md → Testing を参照してください。BrowserResponse についても説明しています)。

    各 output.json に、手動で確認した期待値を設定します(savefixture による記録を修正するか、Fixture.save に item= として渡します)。その後、uv run --with pytest python -m pytest fixtures/ を実行すると、保存済みのすべてのページで to_item() が再実行され、フィールドにずれがあれば失敗します。全体の手順については web-poet.md → Testing を参照してください。

  • スパイダー:範囲を限定したテストクロールを実行し、アイテムを確認してください。終了コードが正常でも、それだけを信用しないでください。必ず CLOSESPIDER_ITEMCOUNT または CLOSESPIDER_PAGECOUNT で範囲を限定します。抽出が機能しているか確認するには数件のアイテムで十分であり、スパイダーの検証でサイト全体をクロールする必要はありません。

    cd PROJECT_DIR && uv run scrapy crawl <name> -s CLOSESPIDER_ITEMCOUNT=5 -o items.jsonl
    

    items.jsonl を確認します。フィールドが一貫して null になっていたり、値がおかしかったりする場合、通常はセレクターが原因です。生の HTML が JavaScript のシェルだとわかった場合は、ブラウザーでレンダリングした入力(BrowserPage)に切り替え、フィクスチャを保存し直します。保存される入力は、記録時にページオブジェクトが依存していたものと一致します。根本原因が、依頼されたスパイダーではなくページオブジェクトにある場合でも、対応範囲内であれば修正してください。修正後はクロールを再実行し、items.jsonl をもう一度確認して、フィールドに値が設定されていることを確認します。終了コードが正常であることや終了時の統計情報ブロックは、修正が機能した証拠にはなりません。また、今回の実行結果で確認していないフィールド値を報告してはいけません。

あるフィールドが一貫して null のままなのに、その理由を説明せずスパイダーを完成とみなしてはいけません。修正するか、最終回答で修正しなかった理由(対応範囲外である、または実際にそのページにデータがない)を説明してください。どちらの場合も、該当するフィールド名を明記します。

コメント