Zum Inhalt

So erstellen Sie Screenshots mit Puppeteer für effektives Web Scraping

Puppeteer ist eine Node.js-Bibliothek, die eine leistungsstarke API zur Steuerung von Headless Chrome und Chromium über das DevTools-Protokoll bereitstellt. Eine der nützlichsten Funktionen ist die Möglichkeit, Screenshots von Webseiten und Elementen programmgesteuert zu erfassen.

Für Web-Scraper eröffnet die Möglichkeit, Screenshots mit Puppeteer zu erstellen, eine Vielzahl wertvoller Anwendungsfälle:

  • Visuelles Debuggen von Scraping-Problemen und Testfehlern.
  • Erfassen des Status dynamischer Seiten und SPAs.
  • Überwachung auf visuelle Regressionen und UI-Änderungen.
  • Erstellen von Tutorials und Dokumentationen mit Screenshots für den Kontext.
  • Generieren von Bildressourcen aus Webseiten.

In diesem umfassenden Leitfaden erfahren Sie, wie Sie Puppeteer-Screenshots nutzen können, um Ihre Web-Scraping-Workflows zu verbessern.

Der Aufstieg des Puppenspielers für Web Scraping

Puppeteer wurde erstmals 2017 veröffentlicht und hat in der Web-Scraping-Community eine schnelle Akzeptanz erfahren. Hier sind ein paar Statistiken, die seine Beliebtheit unterstreichen:

  • Über 52,000 Sterne auf Github machen es zu einem der Top-JS-Projekte.
  • Über 3 Millionen wöchentliche Downloads auf NPM.
  • 490 % Wachstum im Vergleich zum Vorjahr bei der Google-Suche nach Puppenspieler im Jahr 2022.

Was zeichnet Puppeteer beim Web-Scraping aus?

Headless-Browser-Steuerung

Puppeteer bietet über das Chrome DevTools-Protokoll die vollständige Kontrolle über einen Headless-Browser. Dies ermöglicht die Replikation von Benutzerinteraktionen zur Automatisierung und zum Scraping dynamischer Inhalte.

Leicht und schnell

Nur kopflos zu sein bedeutet, dass Puppeteer das gesamte UI-Rendering überspringt, das Chromium zu einem Schwergewicht macht. Dies führt zu einer schnellen Leistung beim Scraping im großen Maßstab.

Aktive Entwicklung

Unterstützt durch das Chrome-Team von Google erhält Puppeteer regelmäßige Updates und neue Funktionen, die auf Automatisierungs- und Scraping-Anwendungsfälle zugeschnitten sind.

Einfacher als Selen

Puppeteer konzentriert sich nur auf die Steuerung von Chromium, während Selenium mehrere Browser unterstützt. Die API ist viel übersichtlicher und idiomatischer und daher benutzerfreundlicher.

Aus diesen Gründen wechseln viele Web-Scraper von Selenium/WebDriver zu Puppeteer, um die Geschwindigkeit, Zuverlässigkeit und Leistungsfähigkeit zu verbessern.

Lassen Sie uns nun untersuchen, wie Sie die leistungsstarken Screenshot-Funktionen von Puppeteer nutzen können.

Erfassen ganzseitiger Screenshots

Der einfachste Weg, einen Screenshot einer gesamten Seite zu erstellen, ist die Verwendung von page.screenshot() Verfahren:

// Launch browser
const browser = await puppeteer.launch();

// Open page 
const page = await browser.newPage();
await page.goto(‘https://example.com‘);

// Screenshot
await page.screenshot({
  path: ‘fullpage.png‘ 
});

Dadurch wird das aktuell sichtbare Ansichtsfenster erfasst. Um die gesamte Seitenhöhe zu scannen, legen Sie fest fullPage Option zu true:

await page.screenshot({
  path: ‘longpage.png‘,
  fullPage: true
}); 

Festlegen von Bildoptionen

Das screenshot() Die Methode akzeptiert Optionen zur Steuerung von Typ, Qualität und mehr:

  • type – PNG, JPEG oder WebP. Der Standardwert ist PNG.
  • quality – Für JPEG/WebP liegt die Qualität zwischen 0 und 100. Der Standardwert ist 80.
  • omitBackground – Blendet den standardmäßigen weißen Hintergrund aus und ermöglicht Transparenz.
  • encoding – Kann als Base64 ausgeben, anstatt eine Datei zu speichern.

Um beispielsweise ein JPEG mit hoher Qualität zu speichern:

await page.screenshot({
  path: ‘page.jpeg‘,
  type: ‘jpeg‘,
  quality: 100
});

Tipp: Verwenden Sie webp für eine bessere Komprimierung bei gleicher Qualität. Allerdings kann es bei WebP zu Kompatibilitätsproblemen kommen.

Umgang mit großen Screenshots

Ganzseitige Screenshots können leicht mehrere Megabyte groß sein. Standardmäßig puffert Puppeteer Screenshots vor dem Speichern im Speicher, wodurch die Prozessgrenzen überschritten werden können.

Übergeben Sie die Option, um große Screenshots zu verarbeiten encoding: ‘base64‘ um die Base64-Zeichenfolge anstelle eines Puffers zu erhalten. Speichern Sie dann mit fs.writeFile(), um eine Pufferung des Bildes im Speicher zu vermeiden.

Hier ist ein Beispiel:

const buffer = await page.screenshot({ encoding: ‘base64‘ });

fs.writeFile(‘screenshot.png‘, buffer, ‘base64‘, err => {
  // handle error 
});

Scrollen durch hohe Seiten für ganzseitige Aufnahmen

Um die volle Höhe von Seiten zu erfassen, die länger als das Darstellungsfenster sind, müssen wir zuerst die Seite scrollen.

Hier ist ein Ansatz mit page.evaluate():

// Scroll to bottom  
await page.evaluate(() => {
  window.scrollTo(0, document.body.scrollHeight);
});

// Screenshot full scrollable area
await page.screenshot({ path: ‘longpage.png‘, fullPage: true });

Wir können auch schrittweise scrollen, Screenshots machen und sie dann zu einem einzigen großen Screenshot zusammenfügen. Dadurch wird vermieden, dass das gesamte Bild im Speicher gepuffert werden muss.

Alternative: Als PDF speichern

Eine weitere Möglichkeit, ganzseitige Inhalte zu erfassen: Erstellen Sie ein PDF!

// Generates PDF and saves to disk 
await page.pdf({
  path: ‘page.pdf‘,
  printBackground: true
});

Vorteile von PDFs:

  • Verarbeitet sofort mehrseitige Inhalte.
  • Das Vektorformat führt normalerweise zu kleineren Dateigrößen.
  • Die Druckformatierung bleibt erhalten.

Nachteile:

  • Weniger flexibel für die programmatische Verarbeitung.
  • Begrenzte Gestaltungsmöglichkeiten im Vergleich zu Bildern.
  • Dynamisch gerenderte Inhalte werden möglicherweise nicht erfasst.

Festlegen der Größe des Ansichtsfensters

Standardmäßig verwendet Puppeteer ein Ansichtsfenster von 800 x 600 Pixel. Um genaue ganzseitige Screenshots auf verschiedenen Desktop- und Mobilgeräten zu erhalten, können wir den Ansichtsbereich explizit festlegen:

// 1200px wide desktop 
await page.setViewport({
  width: 1200,
  height: 800  
});

// 400px wide mobile
await page.setViewport({
  width: 400,
  height: 1200 
});

Dann entsprechen die Screenshots der angegebenen Ansichtsfenstergröße.

Elemente erfassen

Zusätzlich zu ganzseitigen Screenshots können wir mit Screenshots von bestimmten Elementen erfassen element.screenshot().

// Get reference to element
const menu = await page.$(‘.main-menu‘);

// Screenshot just that element
await menu.screenshot({path: ‘menu.png‘});

Das Element wird vor der Aufnahme des Screenshots in die Ansicht gescrollt. Auf diese Weise können Sie Aufnahmen von Elementen machen, die sich möglicherweise außerhalb des Bildschirms befinden, ohne dass Sie zu ihnen scrollen müssen.

Einige Anwendungsfälle für Element-Screenshots:

  • Erfassen von Screenshots dynamischer Komponenten wie Ticker oder Animationen.
  • Beheben von Layoutproblemen durch Aufnehmen einzelner Elemente.
  • Bildressourcen von Symbolen und Illustrationen abrufen.

Screenshots von Offscreen-Elementen

Ein häufiges Problem besteht darin, dass Elemente verdeckt oder verschoben werden, wenn versucht wird, Screenshots während Interaktionen aufzunehmen.

Wir können das automatische Element beim Einscrollen nutzen element.screenshot() um Elemente in jedem Zustand zuverlässig zu erfassen, auch außerhalb des Bildschirms:

// Click button which hides the element 
await page.click(‘.toggle-menu‘);

// Menu is now hidden but we can still screenshot it
await menu.screenshot({path: ‘hidden-menu.png‘}); 

Dies ermöglicht ein einfaches Screenshoting, ohne den Seitenstatus zurückzusetzen.

Warten auf das Laden dynamischer Inhalte

Wenn wir mit dynamischen Seiten arbeiten, möchten wir warten, bis der Inhalt gerendert wird, bevor wir Screenshots machen, um den gewünschten Zustand zu erfassen.

Hier ist ein Beispiel, das darauf wartet, dass ein Element angezeigt wird:

// Click button to trigger ajax call
await page.click(‘.load-content‘);

// Wait for new content to load
await page.waitForSelector(‘.loaded‘);

// Screenshot after loaded
await page.screenshot({path: ‘loaded.png‘}); 

page.waitForSelector() wartet, bis der Selektor im DOM vorhanden ist, bevor fortgefahren wird.

Einige andere nützliche Wartezeiten sind:

  • page.waitFor() – Warten Sie, bis eine bestimmte Bedingung wahr ist.
  • page.waitForFunction() – Warten Sie, bis die asynchronen DOM-Updates abgeschlossen sind.
  • page.waitUntil() – Warten Sie, bis die Navigation erfolgt.

Der Schlüssel liegt darin, die richtige Wartebedingung für die Seitenaktualisierung auszuwählen, die Sie in einem Screenshot festhalten möchten.

Warten auf bestimmte DOM-Änderungen

Um mit diskreteren DOM-Änderungen zu synchronisieren, können wir auf die Aktualisierung von Attributen statt auf pauschale Selektoren warten:

// Wait for text content to change
await page.waitForFunction(() => {
  return document.querySelector(‘.status‘).textContent === ‘Loaded‘; 
});

// Element updated  
await page.screenshot({/*...*/});

Dieser Ansatz eignet sich gut zum Warten auf das Laden von Schlüsseldaten und nicht zum Warten auf statische DOM-Änderungen.

Umgang mit Single Page Apps (SPAs)

Das Warten auf DOM-Änderungen kann bei komplexen JavaScript-SPAs, die den Status aktualisieren, ohne sie neu zu laden, schwierig sein.

Einige Tipps zum Umgang damit:

  • Warten Sie, bis das Netzwerk nach Interaktionen inaktiv ist, damit XHRs abgeschlossen werden können.
  • Warten Sie, bis bestimmte Komponenten wie Overlays anstelle von pauschalen Selektoren verschwinden.
  • Scrollen Sie zum gewünschten Abschnitt, um das Rendern zu erzwingen, bevor Sie einen Screenshot erstellen.
  • Verwenden Sie inkrementelle Wartezeiten anstelle fester Zeitüberschreitungen.

Kein einzelner Ansatz funktioniert perfekt für alle SPAs. Sie müssen mit der jeweiligen App experimentieren.

Scrollen Sie durch die Seiten, bevor Sie ganzseitige Screenshots erstellen

Bei Seiten, die einen Bildlauf erfordern, müssen wir programmgesteuert scrollen, bevor wir einen vollständigen Screenshot erstellen können fullPage: true.

Hier ist ein zuverlässiger Ansatz:

await page.evaluate(() => {
  // Scroll to bottom
  window.scrollTo(0, document.body.scrollHeight);
}); 

// Capture full scrolled screenshot  
await page.screenshot({fullPage: true});

Dadurch wird die Seite bis zur maximalen Bildlaufposition nach unten gescrollt, bevor der Screenshot erstellt wird.

Eine Alternative ist die Verwendung window.scrollBy() um schrittweise jeweils um einen bestimmten Betrag zu scrollen. Dadurch ist es möglich, fortlaufend Screenshots zu machen, während über die gesamte Seitenlänge nach unten gescrollt wird.

Umgang mit langen scrollbaren Seiten

Bei extrem langen Seiten kann das Scrollen über die gesamte Länge auf einmal dennoch zu einer Überschreitung des Speicher- oder Zeitlimits führen.

Eine gute Lösung besteht darin, es in Abschnitte zu unterteilen, jeweils ein Stück zu scrollen, Screenshots zu machen und sie zusammenzufügen:

const screenshots = [];

while (hasMoreContent()) {

  await page.evaluate(scrollDown);

  screenshots.push(await page.screenshot()); 

}

// Stitch screenshots together into one tall image

Dadurch wird vermieden, dass die gesamte Seitenhöhe im Speicher gepuffert werden muss.

Auch horizontal scrollen

Bei Seiten mit horizontalem Scrollen können wir die Scrollsequenz so anpassen, dass auch horizontal gescrollt wird:

await page.evaluate(() => {
  window.scrollTo(
    document.body.scrollWidth, 
    document.body.scrollHeight
  );
});

await page.screenshot({fullPage: true});

Dadurch wird die gesamte Seitenbreite und -höhe erfasst!

Best Practices für zuverlässige Screenshots

Hier sind ein paar wichtige Tipps für die Erstellung konsistenter und zuverlässiger Screenshots mit Puppeteer:

Warten Sie, bis das Netzwerk inaktiv ist - Benutzen page.waitForNetworkIdle() nach Interaktionen, um sicherzustellen, dass alle asynchronen Anforderungen abgeschlossen sind, bevor der Status erfasst wird.

Verwenden Sie geeignete Wartezeiten – Wählen Sie bedingte Wartezeiten, die mit dem gewünschten Seitenstatus synchronisiert werden, statt pauschale Zeitüberschreitungen.

Stellen Sie die Größe des Ansichtsfensters ein – Legen Sie das Ansichtsfenster explizit fest, um genaue Geräte-Screenshots zu erfassen.

Schutz vor Animationen/Popups – Schwebende Elemente können Veränderungen auslösen – Nutzung page.evaluate() um Nebenwirkungen zu vermeiden.

Nehmen Sie sich Zeit zum Rendern – Warten Sie nach dem Scrollen einige hundert Millisekunden, bis die Seiten vollständig gerendert sind, bevor Sie Screenshots erstellen.

Stabilisieren Sie flockige Tests – Legen Sie eine Wiederholungsschleife mit Wartezeiten um Screenshot-Schritte fest, um Flakes zu verarbeiten.

Vergleichen Sie es mit bekanntem Gut – Nutzen Sie visuelle Regressionstest-Tools, um unbeabsichtigte Änderungen zu erkennen.

Zusammenfassung

Ich hoffe, dass dieser Leitfaden einen umfassenden Überblick über die Erstellung ganzer Seiten- und Element-Screenshots mit Puppeteer für Ihre Web-Scraping-Anforderungen bietet.

Einige wichtige Themen, die wir behandelt haben:

  • Verwenden von page.screenshot() und element.screenshot() zum Aufnehmen von Screenshots
  • Optionen zur Steuerung von Bildtyp, Qualität und Format
  • Seiten scrollen und auf dynamischen Inhalt warten
  • Festlegen der Darstellungsgröße für responsive Seiten
  • Best Practices für zuverlässige Screenshot-Workflows

Automatisierte Screenshots sind für das Debuggen von Scrapern, visuelle Tests und die Erfassung dynamischer Zustände von unschätzbarem Wert. Fügen Sie sie mit Puppeteer zu Ihrem Web-Scraping-Toolkit hinzu!

Stichworte:

Mitreden

E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind MIT * gekennzeichnet. *