Ein Großteil der Inhalte, die man von einer Seite möchte, steckt nicht in der ersten Antwort. Social Feeds, Produktraster, Suchergebnisse und Bewertungslisten laden oft eine Handvoll Elemente und rufen dann per Scroll zum unteren Rand mehr ab und rendern diese. Dieses Muster, Infinite Scroll, hält die anfängliche Seite schlank, bedeutet aber auch, dass eine einzelne HTTP-Anfrage nur einen Bruchteil der im Browser sichtbaren Daten liefert.

Dieser Leitfaden zeigt, wie man eine Website beim Crawlen scrollt mit JavaScript und Node.js. Sie erstellen einen kleinen, lauffähigen Scraper, der das Scrollen über die Crawling API mit deren scroll- und scroll_interval-Optionen steuert, die Seite mehr Elemente laden lässt, den geladenen Inhalt dann mit Cheerio parst und exportiert. Die Anleitung verwendet eine neutrale Platzhalter-URL für Angebote, sodass Sie Ihr eigenes öffentliches Ziel einsetzen können, und beschränkt sich auf öffentliche Daten.

Was Sie erstellen werden

Ein Node.js-Skript, das auf eine öffentliche Infinite-Scroll-Angebotsseite zeigt, die Crawling API anweist, sie zu rendern und für eine festgelegte Anzahl von Sekunden weiterzuscrollen, damit mehr Elemente laden, und dann pro Element aus dem zurückgegebenen HTML einen strukturierten Datensatz extrahiert. Das Laufbeispiel zieht eine generische öffentliche Angebotsliste mit diesen Feldern:

  • Title der Elementtitel oder die Überschrift auf der Karte.
  • Subtitle eine sekundäre Zeile wie Anbieter, Autor oder Kategorie, wenn vorhanden.
  • Price der gelistete Preis oder Wert, wenn die Karte einen zeigt.
  • Link die absolute URL zur einzelnen Elementseite.
  • Result count eine zusammenfassende Anzahl, wie viele Elemente die Seite meldet.

Warum eine einfache Anfrage gescrollte Inhalte verpasst

Senden Sie eine einfache HTTP-Anfrage an eine Infinite-Scroll-Seite, erhalten Sie das Markup zurück, das der Server zurückgegeben hat, bevor irgendein Scrollen stattgefunden hat. Das ist üblicherweise das erste Elementpaket und nicht mehr. Der Rest der Liste wird durch das eigene JavaScript der Seite in Reaktion auf Scroll-Ereignisse geladen, oft über Hintergrund-AJAX-Aufrufe, und erst nach dem Scrollen des Browsers ins DOM eingebunden. Eine Anfrage, die nie scrollt, löst diese Aufrufe nie aus, sodass die zusätzlichen Elemente im empfangenen HTML nie existieren.

Damit die vollständige Liste entsteht, müssen zwei Dinge in einer Anfrage geschehen. Die Seite muss in einem echten Browser gerendert werden, und dieser Browser muss weit genug, lange genug scrollen, um jede Runde des Lazy Loading auszulösen. Man kann das selbst mit einem Headless-Browser aufbauen, der in einer Schleife scrollt und dazwischen wartet, plus einem Pool rotierender IPs, damit das Ziel den Traffic als echten Besucher liest. Die Crawling API fasst all das in einem einzigen Aufruf zusammen: Sie senden die URL mit den gesetzten Scroll-Optionen, sie rendert und scrollt die Seite serverseitig hinter einer vertrauenswürdigen IP und gibt das vollständig geladene HTML zurück, das Sie mit Cheerio parsen.

Drei Dinge, die man wissen muss

Drei Dinge lassen Scrollen über die Crawling API funktionieren. Das JavaScript-Token rendert die Seite in einem echten Browser. Die scroll-Option weist die API an, die Seite nach dem Laden zu scrollen. Die scroll_interval-Option legt fest, wie viele Sekunden sie weiterscrollt, bis zu einem Maximum von 60; danach erfasst die API die geladene Seite und gibt sie zurück.

Voraussetzungen

Einige Dinge sollten vor dem Schreiben von Code vorhanden sein. Keines davon nimmt lange.

JavaScript- und Node.js-Grundkenntnisse. Sie sollten in der Lage sein, ein Node-Skript zu schreiben, auszuführen und Pakete mit npm zu installieren. Falls Sie damit neu sind, erklärt unser Guide zu Web-Scraper mit Node.js erstellen die Grundlagen, die dieses Tutorial voraussetzt.

Node.js 16 oder neuer. Prüfen Sie Ihre Version mit node --version. Falls Sie sie nicht haben, installieren Sie sie von der Node.js-Website oder über einen Versionsmanager wie nvm.

Ein Crawlbase-Konto und JavaScript-Token. Registrieren Sie sich, öffnen Sie Ihr Dashboard und kopieren Sie Ihr JavaScript-Token. Der kostenlose Tarif gibt Ihnen bis zu 5.000 Anfragen ohne Kreditkarte, und Sie zahlen nur für erfolgreiche Anfragen. JavaScript-Anfragen kosten mehr Credits als normale, weil sie die Seite rendern, was beim Scrollen relevant ist. Behandeln Sie das Token wie ein Passwort und halten Sie es aus der Versionskontrolle fern.

Das Projekt einrichten

Erstellen Sie einen Projektordner, initialisieren Sie ihn und installieren Sie die zwei Bibliotheken, die der Scraper benötigt.

bash
node --version

mkdir scroll-scraper && cd scroll-scraper
npm init -y

npm install crawlbase cheerio

Zwei Abhängigkeiten erledigen die Arbeit: crawlbase ist der offizielle Node-Client für die Crawling API, und cheerio parst das zurückgegebene HTML mit einer jQuery-ähnlichen API, sodass Sie Felder per CSS-Selektor extrahieren können. Erstellen Sie eine Datei namens scraper.js in diesem Ordner und fügen Sie den Code aus den folgenden Schritten hinzu.

Schritt 1: Die Seite mit aktiviertem Scrollen abrufen

Beginnen Sie damit, die geladene Seite zu erhalten. Importieren Sie die CrawlingAPI-Klasse, initialisieren Sie sie mit Ihrem JavaScript-Token und rufen Sie die Ziel-URL mit der aktivierten scroll-Option ab. Ohne scroll_interval verwendet die API standardmäßig einen 10-Sekunden-Scroll, der das erste zusätzliche Paket lädt. Die Statusprüfung vor dem Parsen sorgt dafür, dass Fehler laut statt lautlos scheitern.

javascript
const { CrawlingAPI } = require('crawlbase');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' });

const targetUrl = 'https://example.com/listings';

api
  .get(targetUrl, { scroll: true })
  .then((response) => {
    if (response.statusCode === 200) {
      console.log(response.body.length, 'bytes of rendered HTML');
      console.log(response.body.slice(0, 500));
    }
  })
  .catch((error) => console.error('API request error:', error));

Führen Sie das Skript mit node scraper.js aus. Das Übergeben von { scroll: true } weist die Crawling API an, die Seite zu rendern und zu scrollen, bevor sie zurückgegeben wird, sodass das erhaltene HTML bereits die beim Scrollen geladenen Elemente enthält, nicht nur das erste Paket. Die Byteanzahl und der Ausschnitt am Anfang des Bodys bestätigen, dass Sie eine echt gerenderte Seite erhalten und keine leere Hülle. Da Sie noch kein Intervall gesetzt haben, wird standardmäßig 10 Sekunden gescrollt, was natürlich weniger Elemente lädt als ein längerer Zeitraum.

Crawlbase Crawling API

Dieser einzelne Aufruf hat gerade eine Infinite-Scroll-Seite für Sie gerendert und gescrollt, ohne einen in einer Schleife scrollenden Headless-Browser oder einen Proxy-Pool auf Ihrer Seite. Die Crawling API führt die Seite in einem echten Browser aus, scrollt so lange wie scroll_interval vorgibt, rotiert serverseitig Residential-IPs und übernimmt CAPTCHAs, sodass Sie das vollständig geladene HTML aus einer Anfrage erhalten. Probieren Sie es mit einer öffentlichen Angebotsliste im kostenlosen Tarif aus und fügen Sie dann Ihren Parser hinzu.

Schritt 2: Mehr Elemente mit scroll_interval laden

Der standardmäßige 10-Sekunden-Scroll lädt nur das erste zusätzliche Paket. Um mehr zu laden, setzen Sie scroll_interval auf die Anzahl der Sekunden, die die API weiterscrollen soll. Das Maximum beträgt 60 Sekunden; danach erfasst die API was auch immer geladen ist und gibt es zurück. Jede zusätzliche Scrollsekunde gibt der Seite mehr Zeit, weitere Elemente abzurufen und zu rendern.

javascript
const { CrawlingAPI } = require('crawlbase');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' });

async function fetchScrolled(url, seconds) {
  const response = await api.get(url, {
    scroll: true,
    scroll_interval: seconds,
  });

  if (response.statusCode === 200) return response.body;
  console.error(`Request failed: ${response.statusCode}`);
  return null;
}

fetchScrolled('https://example.com/listings', 20)
  .then((html) => html && console.log(html.length, 'bytes after 20s scroll'));

Hier scrollt der Aufruf 20 Sekunden statt der standardmäßigen 10, sodass die Seite Zeit hat, mehr Elemente zu laden, und das zurückgegebene HTML ist entsprechend größer. Halten Sie Ihre Verbindung lange genug offen, damit das Scrollen beendet werden kann: Wenn Sie die vollen 60 Sekunden scrollen, erlauben Sie bis zu etwa 90 Sekunden für den Abschluss der Anfrage, bevor die geladene Seite zurückkommt. Starten Sie mit einem kleineren Intervall und erhöhen Sie es nur, bis die Elementanzahl aufhört zu wachsen, da längere Renders mehr kosten und wenig bringen, sobald die Liste erschöpft ist.

Intervall anpassen

Es gibt keinen einzigen richtigen Wert für scroll_interval. Ein kurzer Feed kann in 10 bis 20 Sekunden vollständig geladen sein, während ein langer bis zum 60-Sekunden-Limit weiterlädt. Erhöhen Sie das Intervall schrittweise und vergleichen Sie, wie viele Elemente Sie parsen; sobald die Anzahl nicht mehr steigt, gibt ein längerer Scroll nur Credits aus ohne weitere Zeilen hinzuzufügen.

Schritt 3: Die geladenen Elemente mit Cheerio parsen

Mit dem geladenen HTML übergeben Sie es an Cheerio und durchlaufen jede Elementkarte. Verwenden Sie Selektoren, die zu Ihrem echten Ziel passen; die folgenden setzen eine generische Angebotsliste voraus, bei der jedes Element in einer .listing-item-Karte sitzt. Das defensive Lesen jedes Feldes verhindert, dass ein fehlender Wert den gesamten Lauf zum Absturz bringt.

javascript
const cheerio = require('cheerio');

function parseItems(html, baseUrl) {
  const $ = cheerio.load(html);
  const result = {
    resultCount: $('.results-count').text().trim(),
    items: [],
  };

  $('.listing-item').each((_, element) => {
    const card = $(element);

    const title = card.find('.item-title').text().trim();
    const subtitle = card.find('.item-subtitle').text().trim();
    const price = card.find('.item-price').text().trim();
    let link = card.find('a.item-link').attr('href');
    if (link && link.startsWith('/')) {
      link = new URL(link, baseUrl).href;
    }

    if (title) {
      result.items.push({
        title,
        subtitle: subtitle || '',
        price: price || 'N/A',
        link: link || '',
      });
    }
  });

  return result;
}

Die Zusammenfassungsanzahl kommt von .results-count, und jedes Element sitzt in einer .listing-item-Karte. Innerhalb einer Karte kommt der Titel von .item-title, die sekundäre Zeile von .item-subtitle, der Preis von .item-price und der Link vom a.item-link-Anker, aufgelöst zu einer absoluten URL, damit er außerhalb der Seite funktioniert. Da die beim Scrollen geladenen Elemente bereits im HTML stehen, erfasst dieselbe Schleife das erste Paket und jedes spätere in einem einzigen Durchlauf.

Selektoren veralten

Die obigen Klassennamen sind Platzhalter für eine generische Seite. Bei einem echten Ziel öffnen Sie die Live-Seite in den Entwicklertools Ihres Browsers, scrollen bis Elemente laden, und lesen die tatsächliche Klasse oder das Attribut auf jeder Karte. Viele Produktionsseiten verwenden generierte Klassennamen, die sich ohne Vorankündigung ändern, betrachten Sie Selektoren daher als Ausgangspunkt, nicht als Vertrag, und prüfen Sie sie erneut, wenn ein Feld leer zurückkommt.

Schritt 4: Das vollständige Skript mit JSON- und CSV-Export zusammenstellen

Verbinden Sie nun den gescrollten Abruf und das Parsing in einem lauffähigen Skript und schreiben Sie die Datensätze als JSON und CSV auf die Festplatte.

javascript
const fs = require('fs');
const { CrawlingAPI } = require('crawlbase');
const cheerio = require('cheerio');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' });

async function fetchScrolled(url, seconds) {
  const response = await api.get(url, {
    scroll: true,
    scroll_interval: seconds,
  });
  if (response.statusCode === 200) return response.body;
  console.error(`Request failed: ${response.statusCode}`);
  return null;
}

function toCsv(rows) {
  const headers = ['title', 'subtitle', 'price', 'link'];
  const escape = (value) =>
    `"${String(value).replace(/"/g, '""')}"`;
  const lines = [headers.join(',')];
  for (const row of rows) {
    lines.push(headers.map((h) => escape(row[h])).join(','));
  }
  return lines.join('\n');
}

async function main() {
  const url = 'https://example.com/listings';
  const html = await fetchScrolled(url, 20);
  if (!html) return;

  const data = parseItems(html, url);
  fs.writeFileSync('items.json', JSON.stringify(data, null, 2));
  fs.writeFileSync('items.csv', toCsv(data.items));
  console.log(`Saved ${data.items.length} items to JSON and CSV`);
}

main();

Fügen Sie die parseItems-Funktion aus Schritt 3 in dieselbe Datei ein, damit main sie aufrufen kann. Führen Sie es mit node scraper.js aus, und Sie erhalten zwei Dateien: items.json mit den vollständigen strukturierten Datensätzen und items.csv, die sich direkt in einer Tabellenkalkulation öffnen lässt. Der toCsv-Helfer setzt jedes Feld in Anführungszeichen und verdoppelt eingebettete Anführungszeichen, was wichtig ist, weil Titel und Preise oft Kommas enthalten. Sie haben jetzt einen funktionierenden Scroll-Scraper in deutlich unter 50 Zeilen, den Sie in einen bestehenden Scraper einbauen oder später in einen Endpunkt einwickeln können, wenn gewünscht.

Wie die Ausgabe aussieht

Die JSON-Datei enthält die Ergebnisanzahl plus ein Objekt pro geladenem Element, jedes mit Titel, Untertitel, Preis und Link.

json
{
  "resultCount": "248 results",
  "items": [
    {
      "title": "Wireless Headphones",
      "subtitle": "AudioWorks",
      "price": "$59.00",
      "link": "https://example.com/listings/wireless-headphones"
    },
    {
      "title": "Mechanical Keyboard",
      "subtitle": "KeyForge",
      "price": "$89.00",
      "link": "https://example.com/listings/mechanical-keyboard"
    }
  ]
}

Die CSV spiegelt dieselben Elementzeilen mit einer Kopfzeile wider, sodass sie direkt in Excel, Google Sheets oder jede Pipeline fällt, die durch Trennzeichen getrennte Dateien liest.

csv
title,subtitle,price,link
"Wireless Headphones","AudioWorks","$59.00","https://example.com/listings/wireless-headphones"
"Mechanical Keyboard","KeyForge","$89.00","https://example.com/listings/mechanical-keyboard"

Über eine gescrollte Seite hinaus skalieren

Scrollen lädt mehr Elemente auf einer einzelnen URL, ist aber kein Ersatz für Paginierung, und es gibt eine praktische Obergrenze. Das 60-Sekunden-Limit und die eigene Ladegeschwindigkeit der Seite begrenzen, wie viele Elemente eine Anfrage erschließen kann. Für einen größeren Abruf kombinieren Sie beide Techniken: Scrollen Sie jede Seite, um ihr volles Paket zu laden, dann wechseln Sie zur nächsten Seite, wenn die Website paginiert, und parsen Sie jede mit derselben Funktion.

javascript
async function scrapeAllPages(baseUrl, maxPages, seconds) {
  const allItems = [];

  for (let page = 1; page <= maxPages; page++) {
    const pageUrl = `${baseUrl}?page=${page}`;
    const html = await fetchScrolled(pageUrl, seconds);
    if (!html) break;

    const { items } = parseItems(html, baseUrl);
    if (items.length === 0) break;

    allItems.push(...items);
    console.log(`Page ${page}: ${items.length} items`);

    await new Promise((r) => setTimeout(r, 2000));
  }

  return allItems;
}

Passen Sie das Seitenmuster Ihrem Ziel an, indem Sie einen echten "Nächste Seite"-Link im Browser prüfen. Für hohe Volumina müssen Sie diese Anfragen nicht einzeln nacheinander ausführen. Der asynchrone Crawler lässt Sie viele URLs einreichen und die Ergebnisse einsammeln, wenn sie fertig sind, was für große Scroll-plus-Paginierungs-Jobs besser geeignet ist als eine enge serielle Schleife. Mehr zu gerenderten, skriptlastigen Seiten wie diesen finden Sie in unserem Guide zu JavaScript-Websites crawlen, und für vollständig Hintergrund-AJAX-Feeds unter Daten von AJAX-Websites scrapen.

Verantwortungsvoll scrapen

Beschränken Sie das auf öffentliche Daten und betreiben Sie es rücksichtsvoll. Lesen Sie die Nutzungsbedingungen der Zielwebsite und ihre robots.txt, bevor Sie einen Scroll-Scraper darauf richten, und behandeln Sie beides als Grenze für das, was Sie erfassen. Bleiben Sie bei öffentlichen Angeboten, nicht bei irgendetwas hinter einem Login, und drosseln Sie Ihre Anfragen, um den Server nicht zu belasten: Scrollen hält bereits einen Render für viele Sekunden offen, fügen Sie daher eine Verzögerung zwischen Seiten hinzu statt sie in einer engen Schleife zu feuern. Wenn die Daten identifizierbare Personen betreffen, gelten Datenschutzgesetze wie DSGVO und CCPA, vermeiden Sie also das Zusammenstellen von Profilen über Einzelpersonen und veröffentlichen Sie keine personenbezogenen Daten, die mit jemandem verbunden sind. Das vollständigere Playbook finden Sie unter Websites scrapen ohne geblockt zu werden.

Zusammenfassung

Wichtigste Erkenntnisse

  • Infinite Scroll verbirgt Daten vor einer einfachen Anfrage. Ein einfacher HTTP-Aufruf gibt nur das erste Elementpaket zurück; der Rest lädt beim Scrollen der Seite, sodass eine nie scrollende Anfrage diese nie sieht.
  • Die Crawling API scrollt für Sie. Senden Sie die URL mit scroll: true, und sie rendert die Seite in einem echten Browser, scrollt sie serverseitig hinter einer rotierenden IP und gibt das vollständig geladene HTML in einem Aufruf zurück.
  • scroll_interval steuert, wie viel lädt. Der Standard ist ein 10-Sekunden-Scroll; erhöhen Sie das Intervall bis zum 60-Sekunden-Limit, um mehr Elemente zu laden, und erlauben Sie bis zu etwa 90 Sekunden für den Abschluss einer vollen Längenanfrage.
  • Cheerio parst das geladene HTML. Selektieren Sie jede Elementkarte, lesen Sie Titel, Untertitel, Preis und Link defensiv, rechnen Sie damit, dass generierte Klassennamen sich ändern werden, und exportieren Sie nach JSON und CSV.
  • Scroll plus Paginierung für Skalierung. Scrollen Sie jede Seite, um ihr volles Paket zu laden, wechseln Sie zur nächsten Seite, wenn die Website paginiert, drosseln Sie Anfragen und greifen Sie für große Jobs auf den asynchronen Crawler zurück.

Häufig gestellte Fragen

Was ist Infinite Scroll und warum bricht es einfaches Scraping?

Infinite Scroll ist ein Muster, bei dem eine Seite zuerst eine kleine Menge von Elementen lädt, dann mehr abruft und rendert, wenn der Nutzer zum unteren Rand scrollt, üblicherweise über Hintergrund-AJAX-Aufrufe. Eine einfache HTTP-Anfrage erfasst die Seite, bevor irgendein Scrollen stattgefunden hat, sodass sie nur das erste Paket sieht. Um den Rest zu erhalten, müssen Sie die Seite in einem echten Browser rendern und tatsächlich scrollen, was die Crawling API tut, wenn Sie die Scroll-Optionen übergeben.

Was bewirken die scroll- und scroll_interval-Optionen?

Die scroll-Option weist die Crawling API an, die Seite nach dem Laden zu scrollen, was das Lazy Loading auslöst, das mehr Elemente einbringt. Die scroll_interval-Option legt fest, wie viele Sekunden sie weiterscrollt, bis zu einem Maximum von 60. Mit aktiviertem scroll und ohne gesetztes Intervall scrollt die API standardmäßig 10 Sekunden. Beide erfordern das JavaScript-Token, da die Seite in einem echten Browser gerendert werden muss, damit Scrollen etwas bedeutet.

Wie lange soll ich scroll_interval setzen?

Klein anfangen und erhöhen. Ein kurzer Feed kann in 10 bis 20 Sekunden vollständig geladen sein, während ein langer bis zum 60-Sekunden-Limit weiterlädt. Erhöhen Sie das Intervall schrittweise und vergleichen Sie, wie viele Elemente Sie parsen; sobald die Anzahl aufhört zu wachsen, gibt ein längerer Scroll nur extra Credits aus ohne weitere Zeilen hinzuzufügen. Wenn Sie die vollen 60 Sekunden scrollen, erlauben Sie bis zu etwa 90 Sekunden für den Abschluss der Anfrage.

Benötige ich das JavaScript-Token, um eine Seite zu scrollen?

Ja. Scrollen ergibt nur bei einer Seite Sinn, die in einem echten Browser rendert, und das JavaScript-Token ist das, was dieses Rendering ermöglicht. Ein normales Token gibt das ungerenderte HTML zurück, wo Scrollen keine Wirkung hat und die zusätzlichen Elemente nie laden. JavaScript-Anfragen verbrauchen mehr Credits als normale wegen des Renderings, berücksichtigen Sie das bei der Planung eines großen Laufs.

Ist Scrollen ein Ersatz für Paginierung?

Nein. Scrollen lädt mehr Elemente auf einer URL, aber das 60-Sekunden-Limit und die Ladegeschwindigkeit der Seite begrenzen, wie viele sie in einer einzelnen Anfrage erschließen kann. Für einen vollständigen Datensatz auf einer Website, die auch paginiert, kombinieren Sie beides: Scrollen Sie jede Seite, um ihr volles Paket zu laden, dann wechseln Sie zur nächsten Seite und parsen Sie sie mit derselben Funktion. Für große Jobs erledigt der asynchrone Crawler viele solcher Anfragen parallel.

Meine Selektoren geben nach dem Scrollen leere Werte zurück. Was ist falsch?

Üblicherweise eines von zwei Dingen. Entweder hat die Seite nicht lange genug gescrollt, sodass die gewünschten Elemente nie geladen wurden; in diesem Fall erhöhen Sie scroll_interval und bestätigen, dass das zurückgegebene HTML größer wurde. Oder das Markup der Website verwendet andere oder generierte Klassennamen als Ihre Selektoren erwarten. Öffnen Sie die Live-Seite in den Entwicklertools Ihres Browsers, scrollen bis Elemente erscheinen, lesen Sie die tatsächliche Klasse oder das Attribut auf jeder Karte, und aktualisieren Sie die Selektoren in parseItems entsprechend.

Jetzt loslegen

Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.

Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.

Self-Service · Kein Verkaufsgespräch erforderlich · Enterprise-Crawl-Volumen verfügbar