Scraping
Skill PIXARTSeu/Synapse/packages/codegraph/data/skill/scraping
Web scraping and reverse engineering knowledge base - Playwright, site analysis, asset extraction, SPA scraping. Use when scraping websites, reverse-engineering layouts, extracting assets, or analyzing competitor sites.From its SKILL.md
npx -y skills add PIXARTSeu/Synapse --skill scrapingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.7 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
Scraping & Reverse Engineering Skill
Knowledge base per l'analisi tecnica, il reverse engineering e la clonazione di siti web moderni (SPA, SSR) utilizzando Playwright.
Setup Ambiente
L'agente @web-analyst opera in due modalità:
- Analisi Rapida: Utilizza l'MCP Server di Playwright per ispezione immediata.
- Clonazione Profonda: Scrive ed esegue script Node.js per scaricare assets e struttura.
Installazione Dipendenze (se necessarie)
npm init -y
npm install playwright node-fetch cheerio fs-extra
npx playwright install chromium
1. Script di Clonazione Completa (Formato A)
Questo script clona un sito ricreando la struttura delle cartelle per la navigazione offline.
// clone-site.js
const { chromium } = require('playwright');
const fs = require('fs-extra');
const path = require('path');
const { URL } = require('url');
const fetch = require('node-fetch');
const TARGET_URL = process.argv[2];
const OUTPUT_DIR = process.argv[3] || './.scraped_data';
if (!TARGET_URL) {
console.error('Usage: node clone-site.js <url> [output_dir]');
process.exit(1);
}
const domain = new URL(TARGET_URL).hostname;
const siteDir = path.join(OUTPUT_DIR, domain);
// Helper per scaricare risorse
async function downloadResource(url, type) {
try {
const resourceUrl = new URL(url, TARGET_URL);
// Ignora domini esterni per assets non critici se non richiesto
if (type !== 'image' && resourceUrl.hostname !== domain) return url;
const relativePath = resourceUrl.pathname === '/' ? 'index.html' : resourceUrl.pathname;
const savePath = path.join(siteDir, relativePath);
// Assicura che la directory esista
await fs.ensureDir(path.dirname(savePath));
// Se esiste già, ritorna il path relativo
if (await fs.pathExists(savePath)) {
return path.relative(path.dirname(path.join(siteDir, 'index.html')), savePath);
}
const res = await fetch(resourceUrl.href);
if (!res.ok) return url;
const buffer = await res.buffer();
await fs.writeFile(savePath, buffer);
// Calcola path relativo per l'HTML
return path.relative(path.dirname(path.join(siteDir, 'index.html')), savePath);
} catch (e) {
console.error(`Failed to download ${url}: ${e.message}`);
return url;
}
}
async function scrape() {
console.log(`Cloning ${TARGET_URL} to ${siteDir}...`);
await fs.ensureDir(siteDir);
const browser = await chromium.launch();
const page = await browser.newPage();
// Anti-bot basic bypass
await page.setExtraHTTPHeaders({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
});
try {
await page.goto(TARGET_URL, { waitUntil: 'networkidle' });
// Scroll per triggerare lazy loading
await page.evaluate(async () => {
await new Promise((resolve) => {
let totalHeight = 0;
const distance = 100;
const timer = setInterval(() => {
const scrollHeight = document.body.scrollHeight;
window.scrollBy(0, distance);
totalHeight += distance;
if (totalHeight >= scrollHeight) {
clearInterval(timer);
resolve();
}
}, 100);
});
});
// Aspetta ancora un po' per sicurezza
await page.waitForTimeout(2000);
// Screenshot full page come riferimento
await page.screenshot({ path: path.join(siteDir, 'full-screenshot.png'), fullPage: true });
// Prendi HTML processato (dopo esecuzione JS)
let html = await page.content();
// TO DO: Parsing HTML per trovare e scaricare assets
// Qui si userebbe cheerio o regex per trovare <img src="...">, <link href="...">
// e chiamare downloadResource() sostituendo i link nell'HTML.
// Per brevità del template, questa logica va implementata dall'agente
// in base alla complessità richiesta.
// Esempio base di salvataggio HTML
await fs.writeFile(path.join(siteDir, 'index.html'), html);
console.log('Cloning complete!');
// Analisi Struttura (Output per Design Team)
const analysis = await page.evaluate(() => {
// Estrai colori
const colors = new Set();
const elements = document.querySelectorAll('*');
elements.forEach(el => {
const style = window.getComputedStyle(el);
colors.add(style.color);
colors.add(style.backgroundColor);
});
// Estrai font
const fonts = new Set();
elements.forEach(el => {
const style = window.getComputedStyle(el);
fonts.add(style.fontFamily);
});
return {
colors: Array.from(colors).slice(0, 20), // Limit
fonts: Array.from(fonts)
};
});
await fs.writeJson(path.join(siteDir, 'analysis.json'), analysis, { spaces: 2 });
} catch (error) {
console.error('Error during scraping:', error);
} finally {
await browser.close();
}
}
scrape();
2. Tecniche di Analisi Competitor
Identificare Framework e Librerie
Cerca indizi nel DOM o nei global variables:
__NEXT_DATA__-> Next.js_reactRootContainer-> React- Classi
text-xl p-4 flex-> Tailwind CSS - Classi
MuiButton-root-> Material UI
Estrarre Design System
Per ricreare componenti fedeli:
- Tipografia: Cattura
font-family,line-height,letter-spacingdei tag H1-H6 e p. - Colori: Estrai variabili CSS root (
:root { --primary: ... }) se presenti, altrimenti computed styles. - Spaziature: Analizza
paddingemargindei container principali.
3. Collaborazione con Design Team
Quando @web-analyst ha finito, deve fornire istruzioni precise:
Per @ui-designer:
## Design Analysis for [Sito]
- **Primary Color**: #0066cc
- **Font**: Inter, sans-serif
- **Roundness**: 8px (border-radius predominante)
- **Shadows**: Soft shadows (`0 4px 6px -1px rgba(...)`)
Per @component-builder:
## Component Structure: Navbar
Il sito usa una navbar sticky con:
- Logo a sinistra
- Link centrali (flex gap-4)
- CTA a destra (Button variant="default")
- Mobile: Hamburger menu che apre Sheet laterale
Best Practices
- Rate Limiting: Inserire sempre
waitForTimeout(1000)tra le richieste di pagine multiple. - User Agent: Ruotare o impostare un UA realistico.
- Robot.txt: Controllare
/robots.txtper vedere sezioni proibite (ma per analisi privata di solito si ignora se non massivo). - Cartelle: Salvare sempre in
.scraped_data/per non commettere file spazzatura nel repo git.
What ships with it: 3 files
2.5 KB alongside SKILL.md
evals/
- evals.json1.4 KB
- trigger_evals.json939 B
- learnings.md222 B