원클릭으로
scrape-codegen-generate
Generate web-poet page object code from per-page extraction analyses
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Generate web-poet page object code from per-page extraction analyses
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Extract structured data (all available fields with values) from a page saved locally as an HTML file, optionally following a schema. Use this skill only to process already downloaded files. Do not invoke when the user provides a URL. When invoking, pass the user's full request verbatim as args — do not pre-parse file paths and don't rephrase it.
Analyze an HTML page to produce field extraction instructions for code generation
Generate web-poet page object code from an extraction spec
Generate a Scrapy spider that wires page objects together
Create a new extraction spec from a URL — explore a detail page, discover fields, quick schema approval
Generate an HTML review page for schema and extracted data verification
| name | scrape-codegen-generate |
| description | Generate web-poet page object code from per-page extraction analyses |
| argument-hint | [work-path] [output-path] [spec-path] |
| allowed-tools | Skill, Bash, Read, Write |
You are generating web-poet page object code. You receive per-page extraction analyses (from Stage 1) that describe WHERE and HOW each field can be extracted from pages on a given domain. Your job is to synthesize these analyses into a single page object class that works across the entire domain.
The raw argument string is $ARGUMENTS. Split it into 3 whitespace-separated positional arguments:
.scrape/.work/spec.scrape/spec/page_object.py.scrape/spec/spec.jsonPlus, taken from the surrounding prompt text (not from the argument string):
@field methods for those fields. When not set, generate all fields found in the analyses.Read web-poet.md and docs-access.md from ${CLAUDE_SKILL_DIR}/../scrape/references/.
Read the schema from {spec_path} — use the properties object inside schema.
Also read data_type from {spec_path}.
If data_type ends with -list, set is_list_type = true.
Read all Stage 1 analysis files from {work_path}/codegen-analyze/:
{work_path}/codegen-analyze/list-1.json
{work_path}/codegen-analyze/list-2.json
...
(or detail-*.json for non-list specs)
For each field in the schema, review all per-page analyses together:
No content filtering — ever. Even if the user's prompt asks to filter, exclude, or limit results by value, do NOT implement that logic in the page object. Page objects extract; spiders filter. Mention in your summary that filtering belongs at the spider level.
Generate a complete, self-contained Python module following the web-poet reference. The code must:
None when a field is not present (never empty string or []).extruct for JSON-LD/microdata, price_parser for prices, jmespath for JSON queries.For non-list types (is_list_type = false), standard structure:
from web_poet import WebPage, field
# ... other imports as needed
class PageObject(WebPage[dict]):
# shared helpers as @cached_property if multiple fields need them
@field
def field_name(self) -> type | None:
# extraction logic
...
For list types (is_list_type = true), use web-poet's SelectorExtractor
(see the "Processors for nested fields" section of the
web-poet fields reference).
Define a private SelectorExtractor subclass for per-item extraction, then
iterate over the container selector in the items field. Each analysis file has
container_selector and per-field relative selectors.
import logging
from web_poet import WebPage, Returns, SelectorExtractor, field, handle_urls
from {project}.items import Product, ProductListItems
logger = logging.getLogger(__name__)
class _ProductExtractor(SelectorExtractor[Product]):
@field
def title(self) -> str | None:
return self.css("h3 a::attr(title)").get()
@field
def price(self) -> str | None:
return self.css("p.price_color::text").get()
@handle_urls("example.com")
class ProductListPage(WebPage, Returns[ProductListItems]):
@field
async def items(self) -> list[Product] | None:
result = []
for el in self.css("article.product_pod"):
try:
result.append(await _ProductExtractor(el).to_item())
except Exception:
logger.error("Failed to extract item from %s", self.url, exc_info=True)
return result or None
Key rules for list-type code:
_<ItemClass>Extractor class (e.g. _ProductExtractor) that extends
SelectorExtractor[ItemClass] and has one @field method per item fielditems field must be async def because to_item() is a coroutineawait extractor.to_item() in try/except Exception with a
logger.error(..., exc_info=True) call — this isolates extraction failures to
individual items and logs a full traceback without aborting the whole listreturn result or None (never return [])self.css(...) on the extractor operates on el, not the full page)ItemClass and WrapperClass from the project's items moduleSave the generated code to {output_path}.
Return a summary of what was generated:
Generated page object with N fields:
name: CSS h1.product-title::text
price: JSON-LD offers.price, fallback to CSS span.price
description: CSS div.product-description (text join)
rating: JSON-LD aggregateRating.ratingValue
image_url: CSS img.product-image::attr(src) + urljoin
Include notes on any fields where consensus was difficult or where extraction may be fragile.