Guide

Web Scraping Avanzato: Gestire Paginazione e Contenuti Dinamici

Vuoi trasformare la raccolta di dati dal web in un processo stabile, scalabile e “ban‑proof”? Con scraping web n8n paginazione puoi costruire workflow resilienti che navigano tra pagine, gestiscono contenuti caricati via JavaScript e riducono i rischi di blocco. In questa guida pratica impari a scegliere quando basta l’HTTP Request e quando serve il rendering lato client per scraping, come implementare la paginazione in n8n con loop su page/offset/cursor, come mantenere uno stato persistente, deduplicare i record estratti e ridurre ban grazie a rate limiting, caching (ETag/Last‑Modified) e rotazione IP. Vedrai snippet pronti all’uso, configurazioni chiave e un framework per qualità dati (selettori, normalizzazione, tracciabilità), oltre alle considerazioni legali/etiche che spesso vengono ignorate. Obiettivo: passare da script fragili a pipeline solide, schedulate con Cron in n8n e monitorate con alert mirati.

📚 Nuovo a n8n? Parti dalla guida completa: cos’è n8n e come funziona.

[IMG: Canvas n8n con Cron → HTTP Request → Code (extract + nextPage) → IF (hasNext) → HTTP Request (next) → … → DB + Slack alert]


Scegliere lo strumento giusto: HTTP Request, servizi headless o API di terze parti

Non tutti i siti sono uguali e non tutte le strategie di scraping lo sono. La prima decisione è tecnica e strategica.

  • Quando basta HTTP Request
  • La pagina restituisce HTML “statico” o espone un endpoint JSON (spesso usato dal frontend).
  • Paginazione prevedibile tramite query param (page, offset, cursor).
  • Nessuna protezione anti‑bot aggressiva.
  • Quando serve rendering lato client per scraping
  • Contenuti caricati via JavaScript (lazy loading, infinite scroll) senza API pubbliche facili da replicare.
  • Elementi critici generati dopo esecuzione JS (prezzi, disponibilità).
  • In questi casi valuta un servizio headless (browser automatizzato) o un’API di scraping specializzata. Integra in n8n tramite HTTP Request verso il servizio, mantenendo in n8n la logica di orchestrazione, paginazione e salvataggio.
  • Criteri di scelta tra approcci
  • Manutenzione: meno dipendenze esterne = meno costi, ma più fragilità su siti dinamici.
  • Volume e robustezza: siti con protezioni anti‑bot (Cloudflare, fingerprint TLS) richiedono rotazione proxy e IP residenziali, o soluzioni “browser‑like”.
  • Compliance: controlla sempre i termini del sito e le policy robot.txt.

Consiglio operativo: parti con HTTP Request e prova a individuare gli endpoint JSON interni. Se non basta, passa a un servizio di rendering; tieni separata l’estrazione (servizio) dall’orchestrazione (n8n), così il passaggio scala meglio.


Paginazione in n8n: loop su page/offset/cursor con scheduling e rate limiting

La paginazione è il cuore di ogni pipeline di scraping affidabile.

  • Modello con page/offset
  • Costruisci l’URL con query dinamiche (page=1, 2, 3…) o offset (0, 50, 100…).
  • Esegui la richiesta, estrai i risultati, verifica se ci sono più pagine.
  • Modello con cursor/nextPage
  • Alcune API restituiscono un cursore o un link next. Gestiscilo in un nodo Code e decidi se proseguire.
  • Scheduling con Cron in n8n
  • Usa un trigger temporizzato (esecuzione ogni 15 minuti/ogni notte) per avviare il job.
  • Esegui solo delta (ultime novità) se l’origine lo consente.
  • Rate limiting per richieste HTTP
  • Inserisci attese brevi tra batch (1–3 s).
  • Usa “Split In Batches” quando processi molte URL per stabilizzare il throughput.

Esempio (estrazione JSON e controllo nextPage, Code node — Run Once For All Items):

// Input atteso dal nodo precedente: response JSON dell'HTTP Request
const res = $input.first().json;
const items = (res.items || []).map((it) => ({
  json: {
    id: it.id,
    title: it.title?.trim() || '',
    url: it.url || '',
    price: Number(it.price ?? 0),
    source: res.source || 'unknown',
    fetchedAt: new Date().toISOString(),
  }
}));

const hasNext = Boolean(res.nextPage || res.nextCursor);
return [
  { json: { hasNext, next: res.nextPage || res.nextCursor || null } },
  ...items
];

[IMG: HTTP Request configurato con query page={{$json.page}} e nodo Code che calcola hasNext/next]


Stato persistente, cursori e deduplica: evitare doppioni e “ricominciare da dove hai lasciato”

Quando la raccolta è ricorrente, la gestione dello stato è cruciale.

  • Gestione dello stato nello scraping
  • Conserva l’ultimo cursore o la pagina elaborata in uno storage persistente (DB) o nello stato del workflow.
  • Mantieni l’ultima “data di aggiornamento” per estrarre solo le novità.
  • Stato persistente con getWorkflowStaticData(‘global’)
  • Usa uno storage globale del workflow per salvare cursori/ultima pagina. Esempio (Code node — Run Once For All Items):
// Salvataggio/lettura cursore globale
const state = getWorkflowStaticData('global');
const lastCursor = state.lastCursor || null;

const input = $input.first().json;
if (input.newCursor) {
  state.lastCursor = input.newCursor;
}
return [{ json: { lastCursor: state.lastCursor || null } }];
  • Deduplica dei record estratti
  • Definisci una chiave unica (id, slug, url canonical). Prima di salvare, scarta duplicati visti nell’esecuzione corrente e in DB.
// All-items: dedup in memoria per url
const rows = $input.all().map(i => i.json);
const seen = new Set();
const out = [];
for (const r of rows) {
  const key = (r.url || '').trim().toLowerCase();
  if (!key || seen.has(key)) continue;
  seen.add(key);
  out.push(r);
}
return out.map(j => ({ json: j }));
  • Tracciabilità
  • Aggiungi “source”, “fetchedAt” e, se utile, un “hashContent” per rilevare cambiamenti nel tempo.

Contenuti caricati via JavaScript: strategie operative e infinite scroll

Molti siti popolari caricano i dati lato client: servono tattiche diverse.

  • Individua l’endpoint JSON
  • Apri la rete (DevTools) e cerca richieste XHR/fetch che restituiscono i dati. Spesso basta replicarle in HTTP Request in n8n con gli header corretti (cookie/sessione, user‑agent).
  • Infinite scroll
  • La pagina richiama un endpoint con “cursor/after/offset”. Riproduci lo schema: HTTP Request → Code (next) → IF (hasNext) → loop.
  • Rendering lato client per scraping
  • Se i dati non sono esposti, usa un servizio headless con rotazione proxy e fingerprinting del browser. Integra via HTTP Request e mantieni in n8n paginazione, dedup e salvataggio.
  • Lazy loading di immagini/dettagli
  • Spesso ci sono endpoint di dettaglio per ogni item. Accodali a un “Split In Batches” → HTTP Request (dettaglio) → arricchisci i record con i campi mancanti.

[IMG: Diagramma a due fasi: Catalogo (JSON/HTML) → Lista URL → Dettaglio (JSON/HTML) → Merge + Salva]


Antibot e resilienza: Cloudflare, rotazione IP, fingerprint e limiti

  • Protezioni anti‑bot come Cloudflare
  • Evita burst: imposta rate limiting per richieste HTTP con attese tra batch.
  • Usa proxy pool e IP residenziali; alterna user‑agent plausibili e mantieni header coerenti (Accept‑Language, Accept, sec‑ch‑ua).
  • Riduci parallelismo: serializza le chiamate più sensibili.
  • Fingerprinting del browser
  • Alcune difese controllano TLS fingerprint e comportamenti JS. Se fallisci, passa a servizi “browser‑like”.
  • Retry con backoff esponenziale
  • Sui 429/5xx, attiva retry progressivo (2s → 5s → 10s). Interrompi dopo N tentativi e invia alert.
  • Osservabilità
  • Logga gli status code, la latenza media e il tasso di errore per dominio. Monitora i ban nel tempo per calibrare batch e attese.

Parsing sicuro e robusto: selettori, normalizzazione e validazione

  • Selettori CSS/XPath con estrattori
  • Per HTML semplice, identifica pattern stabili (class, id); evita selettori fragili.
  • Se ottieni JSON, preferiscilo: parsing più stabile e veloce.
  • Normalizzazione schema
  • Definisci uno schema di output con tipi coerenti (string/number/date) e campi opzionali.
  • Valida i campi chiave (url, price, title) e imposta default sicuri.
  • Qualità dati e tracciabilità
  • Aggiungi sourceUrl, timestamp, e un checksum del record. Questo aiuta ad auditare e a identificare update reali vs rumore.

Esempio (Code — per‑item: normalizza e mappa)

const j = $json;
return {
  json: {
    id: j.id || j.slug || null,
    title: String(j.title || '').trim(),
    url: String(j.url || '').trim(),
    price: Number(j.price ?? 0),
    currency: j.currency || 'USD',
    fetchedAt: new Date().toISOString(),
    source: j.source || 'unknown'
  }
};

Cache e conditional requests: ETag, Last‑Modified e riduzione dei costi/ban

Riduci richieste inutili e rispetta i limiti.

  • ETag e Last‑Modified
  • Salva ETag/Last‑Modified dal response precedente.
  • Nelle richieste successive, invia If‑None‑Match / If‑Modified‑Since. Se ricevi 304 Not Modified, salta parsing e passa oltre.
  • Come farlo in n8n
  • HTTP Request: aggiungi header dinamici con espressioni (If‑None‑Match: ={{$json.etag}}).
  • Gestisci la logica in un nodo IF: se statusCode==304, non aggiornare; altrimenti prosegui e aggiorna ETag/Last‑Modified persistenze.
  • Benefici
  • Meno banda, meno load sul sito target, minor probabilità di ban.

[IMG: HTTP Request con Headers If‑None‑Match/If‑Modified‑Since e IF che intercetta 304]


Salvataggio e indicizzazione: database, dedup e scheduling/alerting

  • Database di destinazione
  • MongoDB/Postgres: scegli in base a volumi e query. Mongo è flessibile per documenti JSON; Postgres+JSONB per query strutturate e join.
  • Imposta un indice univoco sulla chiave (id/url) per prevenire duplicati lato DB.
  • Deduplica dei record estratti
  • Dedup in memoria (per esecuzione) + indice univoco (persistenza). Logga conflitti e scarti per audit.
  • Scheduling con Cron in n8n
  • Pianifica finestre orarie “soft” (notte/weekend) per scraping massivo.
  • Aggiungi alert: invia un riepilogo Slack con conteggio record nuovi/aggiornati, errori e durata.
  • Pipeline a due fasi
  • Catalogo (lista) → Dettaglio (arricchimento) → Merge → Salva. Questa separazione migliora debug e controlli qualità.

Resilienza end‑to‑end: retry, limiti di concorrenza e aspetti legali/etici

  • Retry con backoff esponenziale
  • Implementa retry solo su errori temporanei. Limita i tentativi e aumenta l’attesa per ogni retry.
  • Limiti di concorrenza
  • Evita chiamate parallele elevate su domini sensibili. Meglio batch piccoli e costanti.
  • Osservabilità
  • Attiva un workflow con Error Trigger per log centralizzato. Traccia tassi di errore per dominio/source.
  • Aspetti legali/etici
  • Rispetta robots.txt, ToS e privacy. Non raccogliere dati personali senza base legale. Fornisci un meccanismo per eliminare dati se richiesto.

Esempio operativo: paginazione con page e arricchimento dettaglio

Scenario: elenco prodotti con endpoint JSON paginato (page=1..N) e endpoint dettaglio per ogni item.

  1. Cron (ogni notte)

  2. Code (imposta page iniziale, o leggi cursore persistente)

  3. HTTP Request (GET lista?page={{$json.page}})

  4. Code (estrai items, nextPage)

  5. IF (hasNext) → incrementa page → loop al punto 3; altrimenti prosegui

  6. Split In Batches (20)

  7. HTTP Request (GET dettaglio per item.url)

  8. Code (merge campi, normalizza schema)

  9. DB (insert/upsert) con indice unico

  10. Slack (report)

Snippet per incrementare page (Code — per‑item):

const j = $json;
const nextPage = Number(j.page || 1) + 1;
return { json: { page: nextPage } };

[IMG: Canvas con ramo Lista (loop page) e ramo Dettaglio (Split In Batches) fino al DB]


Quick Takeaways

  • Inizia con HTTP Request e punta agli endpoint JSON; passa al rendering lato client solo quando necessario.
  • Implementa la paginazione in n8n con loop su page/offset/cursor, controlli IF e attese tra batch.
  • Mantieni stato e cursori (getWorkflowStaticData(‘global’) o DB) e applica dedup su chiave unica.
  • Riduci ban con rate limiting, caching via ETag/Last‑Modified e rotazione IP su domini “sensibili”.
  • Normalizza e valida i dati prima del salvataggio; traccia source e fetchedAt per audit.
  • Schedula con Cron e invia alert/summary: osservabilità prima di tutto.

Conclusione

Portare scraping web n8n paginazione a livello “produzione” richiede una combinazione di scelte strategiche e tattiche: puntare prima agli endpoint JSON, orchestrare la paginazione con loop chiari e stato persistente, assicurare qualità e dedup, e proteggere il ciclo con rate limiting, caching e retry intelligenti. Con un disegno a due fasi (lista → dettaglio), salvataggio su DB con indice unico e un layer di observability (Slack report, Error Trigger), i tuoi workflow diventano affidabili e prevedibili. Per i marketer, significa dati freschi e puliti per campagne, pricing intelligence e analisi competitive, senza il peso di manutenzioni continue. Parti da un MVP con pochi endpoint, misura tempi/ban/errori, poi scala con batching e caching: il salto di qualità è nel processo, non solo nel parser.


FAQ

  1. Come gestisco la paginazione in n8n senza rischiare loop infiniti?

Controlla sempre un segnale di uscita (no results/hasNext=false). Incrementa page/offset in un Code node, valida i limiti e usa IF per interrompere quando non ci sono più dati.

  1. Come tratto contenuti caricati via JavaScript?

Cerca gli endpoint JSON usati dal frontend. Se non esistono o sono offuscati, integra un servizio di rendering lato client e usa n8n per orchestrazione, paginazione e salvataggio.

  1. Come riduco i ban su siti protetti (Cloudflare)?

Diminuisci parallelismo, aggiungi attese tra batch, usa proxy/rotazione IP residenziali e header plausibili. Implementa retry con backoff sui 429/5xx e monitora i tassi di errore per dominio.

  1. Posso usare caching con ETag/Last‑Modified in n8n?

Sì. Salva ETag/Last‑Modified e inviali come If‑None‑Match/If‑Modified‑Since negli header dell’HTTP Request. Gestisci i 304 per saltare parsing e ridurre richieste.

  1. Qual è il modo migliore per evitare duplicati nel database?

Definisci una chiave unica (id/url canonical) e crea un indice unico nel DB. In n8n, aggiungi anche una dedup in memoria per esecuzione, loggando i record scartati.


Ci dai una mano?

Qual è il tuo prossimo target: stabilizzare la paginazione, ridurre i ban con caching/limiti o arricchire i dati con un passo “dettaglio”? Condividi la tua scelta e questo articolo con il team: confrontiamo pattern e trasformiamo gli scraper in pipeline affidabili!

Articoli correlati

Vuoi automazioni AI su misura per la tua azienda?
Scopri la consulenza →

Partiamo da un processo che oggi vi costa ore

Su WhatsApp risponde una persona, di solito in giornata. Se preferisci scrivere con calma, c’è il modulo qui sotto.

Scrivici su WhatsApp

Raccontaci cosa vuoi automatizzare

Ti rispondiamo noi, di solito in giornata.

Raccontaci cosa vi fa perdere tempo

Due righe bastano. Vi diciamo se si automatizza, come, e quanto costa. Se non conviene, lo diciamo.