Passo-a-passo detalhado do skill, referenciando as fases cognitivas:
1SENSE — Análise do alvo e planejamento
```python
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()
if not rp.can_fetch("*", url):
raise PermissionError("Scraping not allowed by robots.txt")
crawl_delay = rp.crawl_delay("*") or 1.0
```
Identificar tipo de conteúdo (estático vs. SPA) com HEAD request
2CONTEXTUALIZE — Inspecionar estrutura HTML
Analisar 3-5 páginas manualmente para identificar seletores estáveis
Preferir data-attributes (`data-product-id`) sobre classes CSS (podem mudar)
Verificar sitemap.xml: `curl https://example.com/sitemap.xml`
3HYPOTHESIZE — Escolher stack
HTML estático → Cheerio + node-fetch (10x mais rápido)
SPA/dinamico → Playwright (mais robusto, suporte a múltiplos browsers)
Alto volume → Crawlee (queue, proxy rotation, sessões automáticas)
4RECOMMEND — Implementar scraper
```typescript
// Playwright com rate limiting e retry
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (compatible; MyBot/1.0)',
});
for (const url of urls) {
await delay(crawlDelay * 1000); // respeitar robots.txt Crawl-delay
const page = await context.newPage();
await page.goto(url, { waitUntil: 'networkidle', timeout: 30_000 });
const data = await page.evaluate(() => ({ ... }));
results.push(data);
await page.close();
}
```
5EVALUATE — Validar dados extraídos
Verificar cobertura: todos os campos esperados extraídos
Detectar outliers: campos vazios, valores fora do range esperado
Checar encoding: caracteres especiais preservados corretamente
6REFLECT — Qualidade, ética e telemetria
Validar deduplicação: sem URLs ou registros repetidos
Confirmar rate limiting respeitado via logs de timestamp
Reportar telemetria via mcp-skillschain