zytedata/claude-skills · Archived

scrape-create-spider

Generate a Scrapy spider that wires page objects together

First seen Jun 15, 2026

Installation

$ npx skills add zytedata/claude-skills --skill scrape-create-spider

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from zytedata/claude-skills · top by installs.

npx skills add zytedata/claude-skills

Browse all from zytedata/claude-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 25
License LICENSE.md
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsBash, Read, Write, Edit

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,454 B
  • docs SUMMARY.md 85 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 4 installs

SKILL.md

You are generating a Scrapy spider that wires together web-poet page objects (item extraction + navigation) into a working crawler.

Read python-environments.md and docs-access.md from ${CLAUDESKILLDIR}/../scrape/references.

Input

The raw argument string is $ARGUMENTS. Split it into 3 whitespace-separated positional arguments:

  1. project_dir: path to the Scrapy project
  2. itempage: import path of the item extraction PO (e.g. booksproject.pages.bookstoscrapecom.ProductPage)
  3. navpage: import path of the navigation PO (e.g. booksproject.pages.bookstoscrapecom.NavigationPage)

Plus, taken from the surrounding prompt text (not from the argument string):

Process

1. Read the project and spec

Detect the project name from {project_dir}.

Use the provided PO import paths to determine the module and class names for imports. Parse start URLs to derive the spider name from the domain.

Read references/scrapy-poet-reference.md for spider patterns.

Detect list-page mode: Check whether the item_page class name ends with ListPage (e.g., ProductListPage, BookListPage). If it does, use the list-extraction pattern (Step 2b). Otherwise, use the detail-extraction pattern (Step 2a).

2a. Generate a detail-extraction spider (default)

Write a spider to {projectname}/spiders/{spidername}.py.

The spider uses the navigation PO to discover links and the item extraction PO to extract data from individual detail pages. Pattern:

import scrapy
from scrapy_poet import DummyResponse

from {project_name}.pages.{module} import {ItemPage}, {NavPage}


class {SpiderClass}(scrapy.Spider):
    name = "{spider_name}"
    start_urls = ["{start_url}"]

    async def parse(self, response: DummyResponse, nav: {NavPage}):
        """Parse list/category pages — extract navigation links."""
        nav_item = await nav.to_item()

        # Follow item links → item extraction PO
        for link in nav_item.items or []:
            yield scrapy.Request(link["url"], callback=self.parse_item)

        # Follow pagination
        if nav_item.next_page:
            yield scrapy.Request(nav_item.next_page, callback=self.parse)

        # Follow subcategories
        for link in nav_item.subcategories or []:
            yield scrapy.Request(link["url"], callback=self.parse)

    async def parse_item(self, response: DummyResponse, page: {ItemPage}):
        """Extract item data."""
        yield await page.to_item()

Key points:

  • parse is the default callback for start_urls
  • POs are injected via type annotations on callbacks
  • response: DummyResponse since we only need the PO, not raw response
  • Pagination and subcategory links recurse back to parse

2b. Generate a list-extraction spider (when item_page ends with ListPage)

When the item page PO is a list-page extractor (class name ends with ListPage), items are extracted directly from each list/category page — no detail-page requests needed. Both the navigation PO and the list page PO are injected into the same parse callback:

import scrapy
from scrapy_poet import DummyResponse

from {project_name}.pages.{module} import {ListPage}, {NavPage}


class {SpiderClass}(scrapy.Spider):
    name = "{spider_name}"
    start_urls = ["{start_url}"]

    async def parse(self, response: DummyResponse, nav: {NavPage}, list_page: {ListPage}):
        """Extract items from list page and follow navigation links."""
        nav_data = await nav.to_item()
        list_data = await list_page.to_item()

        for item in list_data.items or []:
            yield item

        if nav_data.next_page:
            yield scrapy.Request(nav_data.next_page, callback=self.parse)

        for sub in nav_data.subcategories or []:
            yield scrapy.Request(sub["url"], callback=self.parse)

Key points:

  • Both NavPage and ListPage are injected into parse via type annotations
  • Items come directly from listdata.items — no parseitem callback
  • list_page is the parameter name for the list-page PO injection
  • Pagination and subcategory links recurse back to parse

3. Naming

  • spidername: derive from domain (e.g., bookstoscrape_com)
  • SpiderClass: PascalCase version (e.g., BooksToscrapeCom)
  • module: the page objects module file (same domain-based name)

4. Custom settings (if needed)

If the site requires Zyte API (e.g., detected during spec building), add:

    custom_settings = {
        "ZYTE_API_TRANSPARENT_MODE": True,
    }

Read the scrapy-zyte-api reference:

references/scrapy-zyte-api-reference.md

5. Test the spider and validate items

Run a test crawl that saves items to a file so you can inspect them:

cd {project_dir} && uv run scrapy crawl {spider_name} -s CLOSESPIDER_ITEMCOUNT=5 -o items.jsonl 2>&1

If the crawl fails (non-zero exit, exceptions in output):

  • Check error messages
  • Verify page object imports are correct
  • Verify SCRAPYPOETDISCOVER includes the pages module
  • Try with ZYTEAPILOG_REQUESTS=True if using Zyte API

If the crawl succeeds, read items.jsonl and check for obvious data-quality issues. If you find any, read the relevant page object, diagnose and fix the root cause, delete items.jsonl, and re-run. Repeat up to 2 more times (3 total). If items still look wrong after 3 attempts, stop and report what you found.

Only declare the spider complete once items look correct.

6. Report

For detail-extraction spiders:

Created spider at {project_name}/spiders/{spider_name}.py:
  Start URL: {start_url}
  Navigation: {NavPage} → follows items, pagination, subcategories
  Extraction: {ItemPage} → parse_item callback

Run: cd {project_dir} && uv run scrapy crawl {spider_name}

For list-extraction spiders:

Created spider at {project_name}/spiders/{spider_name}.py:
  Start URL: {start_url}
  Navigation: {NavPage} → follows pagination and subcategories
  Extraction: {ListPage} → items extracted directly from list pages

Run: cd {project_dir} && uv run scrapy crawl {spider_name}