Meteen naar de inhoud

Hoe u screenshots kunt maken met Puppeteer voor effectief webscrapen

Puppeteer is een Node.js-bibliotheek die een krachtige API biedt voor het besturen van Chrome en Chromium zonder hoofd via het DevTools-protocol. Een van de handigste functies is de mogelijkheid om programmatisch schermafbeeldingen van webpagina's en elementen vast te leggen.

Voor webschrapers ontgrendelt de mogelijkheid om schermafbeeldingen te maken met Puppeteer een verscheidenheid aan waardevolle gebruiksscenario's:

  • Visueel debuggen van scrapingproblemen en testfouten.
  • Statussen van dynamische pagina's en SPA's vastleggen.
  • Controle op visuele regressies en UI-wijzigingen.
  • Tutorials en documentatie maken met screenshots voor context.
  • Afbeeldingsitems genereren van webpagina's.

In deze uitgebreide handleiding onderzoeken we hoe u Puppeteer-screenshots kunt gebruiken om uw webscraping-workflows te verbeteren.

De opkomst van poppenspelers voor webscraping

Puppeteer werd voor het eerst uitgebracht in 2017 en werd snel geaccepteerd door de webscraping-gemeenschap. Hier zijn een paar statistieken die de populariteit ervan benadrukken:

  • Meer dan 52,000 sterren op Github, waardoor het een van de beste JS-projecten is.
  • Meer dan 3 miljoen wekelijkse downloads op NPM.
  • 490% groei op jaarbasis in Google-zoekopdrachten naar Puppeteer in 2022.

Dus wat onderscheidt Puppeteer op het gebied van webscrapen?

Headless browserbediening

Puppeteer biedt volledige controle over een headless browser via het Chrome DevTools Protocol. Dit maakt het repliceren van gebruikersinteracties mogelijk voor automatisering en het schrapen van dynamische inhoud.

Lichtgewicht en snel

Omdat hij alleen headless is, slaat Puppeteer alle UI-weergave over die Chromium zwaar maakt. Dit resulteert in snelle prestaties voor schrapen op schaal.

Actieve ontwikkeling

Gesteund door het Chrome-team van Google krijgt Puppeteer regelmatig updates en nieuwe functies die zijn afgestemd op automatisering en scraping-gebruiksscenario's.

Eenvoudiger dan Selenium

Puppeteer richt zich alleen op het besturen van Chromium, terwijl Selenium meerdere browsers ondersteunt. De API is veel schoner en idiomatisch waardoor hij gemakkelijk te gebruiken is.

Om deze redenen schakelen veel webschrapers over naar Puppeteer van Selenium/WebDriver voor verbeterde snelheid, betrouwbaarheid en mogelijkheden.

Laten we nu eens kijken hoe we de krachtige screenshot-mogelijkheden van Puppeteer kunnen benutten.

Schermafbeeldingen van een volledige pagina vastleggen

De eenvoudigste manier om een ​​screenshot van een hele pagina te maken is met behulp van de page.screenshot() methode:

// 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‘ 
});

Hiermee wordt het momenteel zichtbare kijkvenster vastgelegd. Om een ​​screenshot te maken van de volledige paginahoogte, stelt u de fullPage optie om true:

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

Beeldopties opgeven

De screenshot() methode accepteert opties om het type, de kwaliteit en meer te controleren:

  • type – png, jpeg of webp. Standaard is png.
  • quality – Voor jpeg/webp varieert de kwaliteit van 0-100. Standaard is 80.
  • omitBackground – Verbergt de standaard witte achtergrond en maakt transparantie mogelijk.
  • encoding – Kan worden uitgevoerd als base64 in plaats van een bestand op te slaan.

Om bijvoorbeeld een jpeg van hoge kwaliteit op te slaan:

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

Tip: Gebruik webp voor betere compressie met gelijkwaardige kwaliteit. Webp kan echter compatibiliteitsproblemen hebben.

Omgaan met grote screenshots

Schermafbeeldingen van een volledige pagina kunnen gemakkelijk groter zijn dan vele megabytes. Standaard buffert Puppeteer schermafbeeldingen in het geheugen voordat deze worden opgeslagen, waardoor de proceslimieten kunnen worden overschreden.

Geef de optie door om grote schermafbeeldingen te verwerken encoding: ‘base64‘ om de base64-string te krijgen in plaats van een buffer. Sla vervolgens op met fs.writeFile() om te voorkomen dat de afbeelding in het geheugen wordt gebufferd.

Hier is een voorbeeld:

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

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

Door lange pagina's scrollen voor volledige pagina-opnamen

Om de volledige hoogte vast te leggen van pagina's die langer zijn dan de viewport, moeten we eerst door de pagina scrollen.

Hier is één benadering die wordt gebruikt 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 });

We kunnen ook stapsgewijs scrollen door schermafbeeldingen te maken en deze vervolgens samenvoegen tot één grote schermafbeelding. Dit voorkomt dat u de hele afbeelding in het geheugen moet bufferen.

Alternatief: Opslaan als PDF

Een andere optie voor het vastleggen van volledige pagina-inhoud: genereer een PDF!

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

Voordelen van PDF's:

  • Verwerkt inhoud van meerdere pagina's direct uit de doos.
  • Vectorformaat resulteert meestal in kleinere bestandsgroottes.
  • De afdrukopmaak blijft intact.

nadelen:

  • Minder flexibel voor programmatische verwerking.
  • Beperkte stylingopties vergeleken met afbeeldingen.
  • Mogelijk wordt dynamisch weergegeven inhoud niet vastgelegd.

Viewport-grootte instellen

Standaard gebruikt Puppeteer een viewport van 800px x 600px. Om nauwkeurige schermafbeeldingen van een volledige pagina te krijgen op verschillende desktop- en mobiele formaten, kunnen we de viewport expliciet instellen:

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

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

Schermafbeeldingen komen dan overeen met de opgegeven viewportgrootte.

Elementen vastleggen

Naast schermafbeeldingen van de volledige pagina kunnen we schermafbeeldingen maken van specifieke elementen met behulp van element.screenshot().

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

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

Het element wordt in beeld gescrolld voordat de schermafbeelding wordt gemaakt. Hierdoor kunt u opnamen maken van elementen die zich mogelijk buiten het scherm bevinden, zonder dat u ernaartoe hoeft te scrollen.

Enkele gebruiksscenario's voor elementscreenshots:

  • Schermafbeeldingen maken van dynamische componenten zoals tickers of animaties.
  • Problemen met de lay-out oplossen door opnamen te maken van afzonderlijke elementen.
  • Afbeeldingsitems van pictogrammen en illustraties verkrijgen.

Schermafbeeldingen van elementen buiten het scherm

Een veelvoorkomend probleem is dat elementen verborgen of verplaatst worden wanneer je schermafbeeldingen probeert te maken tijdens interacties.

We kunnen gebruik maken van het automatische element dat naar binnen scrollt element.screenshot() om elementen in elke staat betrouwbaar vast te leggen, zelfs als ze niet op het scherm staan:

// 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‘}); 

Hierdoor kunt u eenvoudig screenshots maken zonder de paginastatus opnieuw in te stellen.

Wachten tot dynamische inhoud is geladen

Wanneer we met dynamische pagina's werken, willen we wachten tot de inhoud wordt weergegeven voordat we schermafbeeldingen maken om de gewenste status vast te leggen.

Hier is een voorbeeld dat wacht tot een element verschijnt:

// 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() wacht totdat de selector in de DOM bestaat voordat hij verdergaat.

Enkele andere nuttige wachttijden zijn:

  • page.waitFor() – Wacht tot een bepaalde voorwaarde waar is.
  • page.waitForFunction() – Wacht tot de asynchrone DOM-updates zijn voltooid.
  • page.waitUntil() – Wacht tot de navigatie plaatsvindt.

De sleutel is het kiezen van de juiste wachtvoorwaarde voor de pagina-update die u in een screenshot wilt vastleggen.

Wachten op specifieke DOM-wijzigingen

Om te synchroniseren met meer discrete DOM-wijzigingen kunnen we wachten tot de attributen zijn bijgewerkt in plaats van algemene selectors:

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

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

Deze aanpak werkt goed bij het wachten op het laden van belangrijke gegevens in plaats van bij statische DOM-wijzigingen.

Omgaan met Single Page Apps (SPA's)

Wachten op DOM-wijzigingen kan lastig zijn met complexe JavaScript SPA's die de status bijwerken zonder opnieuw te laden.

Enkele tips om hiermee om te gaan:

  • Wacht tot het netwerk inactief is na interacties, zodat XHR's kunnen worden voltooid.
  • Wacht tot specifieke componenten zoals overlays verdwijnen in plaats van algemene selectors.
  • Scroll naar de gewenste sectie om weergave te forceren voordat u een screenshot maakt.
  • Gebruik incrementele wachttijden in plaats van vaste time-outs.

Geen enkele aanpak werkt perfect voor alle SPA's. Je zult moeten experimenteren met de betreffende app.

Bladeren door pagina's voordat u schermafbeeldingen van de volledige pagina maakt

Voor pagina's waarop moet worden gescrolld, moeten we programmatisch scrollen voordat we een volledige schermafbeelding maken fullPage: true.

Hier is een betrouwbare aanpak:

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

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

Hierdoor schuift de pagina omlaag naar de maximale schuifpositie voordat de schermafbeelding wordt gemaakt.

Een alternatief is gebruiken window.scrollBy() om stapsgewijs een bepaald aantal tegelijk te scrollen. Hierdoor kunt u continu schermafbeeldingen maken terwijl u over de volledige paginalengte naar beneden scrollt.

Omgaan met lange scrollbare pagina's

Bij extreem lange pagina's kan het in één keer scrollen over de hele lengte nog steeds de geheugen- of tijdlimieten overschrijden.

Een goede oplossing is om het in secties op te delen, beetje bij beetje te scrollen, schermafbeeldingen te maken en ze aan elkaar te plakken:

const screenshots = [];

while (hasMoreContent()) {

  await page.evaluate(scrollDown);

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

}

// Stitch screenshots together into one tall image

Dit voorkomt dat u de volledige paginahoogte in het geheugen moet bufferen.

Horizontaal scrollen ook

Voor pagina's met horizontaal scrollen kunnen we de scrollvolgorde aanpassen om ook horizontaal te scrollen:

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

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

Hiermee wordt de volledige paginabreedte en -hoogte vastgelegd!

Best practices voor betrouwbare screenshots

Hier zijn een paar belangrijke tips voor het maken van consistente, betrouwbare schermafbeeldingen met Puppeteer:

Wacht tot het netwerk inactief is - Gebruik page.waitForNetworkIdle() na interacties om ervoor te zorgen dat alle asynchrone verzoeken zijn voltooid voordat de status wordt vastgelegd.

Gebruik passende wachttijden – Kies voorwaardelijke wachttijden die synchroniseren met de gewenste paginastatus in plaats van algemene time-outs.

Stel de viewportgrootte in – Stel de viewport expliciet in om nauwkeurige schermafbeeldingen van apparaten vast te leggen.

Afschermen tegen animaties/pop-ups – Zwevende elementen kunnen veranderingen veroorzaken – gebruik page.evaluate() om bijwerkingen te voorkomen.

Geef tijd voor weergave – Wacht een paar honderd milliseconden na het scrollen naar pagina's om het renderen te voltooien voordat er screenshots worden gemaakt.

Stabiliseer schilferige tests – Stel een herhalingslus in met wachttijden rond screenshot-stappen om vlokken te verwerken.

Vergelijk het met bekend goed – Maak gebruik van visuele regressietesttools om onbedoelde veranderingen op te sporen.

Conclusie

Ik hoop dat deze handleiding een uitgebreid overzicht biedt van het maken van schermafbeeldingen van volledige pagina's en elementen met Puppeteer voor uw webscraping-behoeften.

Enkele belangrijke onderwerpen die we hebben behandeld:

  • Gebruik page.screenshot() en element.screenshot() om schermafbeeldingen te maken
  • Opties voor het regelen van het afbeeldingstype, de kwaliteit en het formaat
  • Pagina's scrollen en wachten op dynamische inhoud
  • Viewportgrootte instellen voor responsieve pagina's
  • Best practices voor betrouwbare screenshot-workflows

Geautomatiseerde schermafbeeldingen zijn van onschatbare waarde voor het debuggen van scrapers, visueel testen en het vastleggen van dynamische toestanden. Voeg ze toe aan uw webscraping-toolkit met Puppeteer!

Doe mee aan het gesprek

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd *