Web-Scraping mit Puppeteer

In dieser Schritt-für-Schritt-Anleitung erfahren Sie, wie Sie mit Puppeteer statische und dynamische Websites scrapen können
9 min read
web scraping with puppeteer

Puppeteer ist eine Bibliothek zum Testen und Automatisieren von Browsern, die auch für das Web Scraping geeignet ist. Im Vergleich zu einfacheren Tools wie Axios und Cheerioermöglicht Puppeteer Entwicklern das Scrapen von dynamischen Inhalten(d. h. Inhalten, die sich aufgrund von Benutzeraktionen ändern).

Das bedeutet, dass Sie damit Webanwendungen (Single Page Apps) scrapen können, die ihren Inhalt mit JavaScript laden. Genau dies werden Sie gleich tun.

Web-Scraping mit Puppeteer  

In dieser Anleitung erfahren Sie, wie Sie statische und dynamische Daten (z. B. Titel von Beiträgen und Links von Bright Data`s Blog) mit Puppeteer scrapen können.  

Einrichten

Bevor Sie mit der Anleitung beginnen, sorgen Sie dafür, dass Sie Node.js auf Ihrem Computer installiert haben. Sie können es von der offiziellen Download-Website herunterladen.

Erstellen Sie nun ein neues Verzeichnis für das Projekt und navigieren Sie mit den folgenden Befehlen dorthin:

mkdir puppeteer_tutorial 
cd puppeteer_tutorial 
npm init -y 

Als nächstes installieren Sie Puppeteer mit diesem Befehl:

npm i puppeteer --save

Mit diesem Befehl wird auch ein spezieller Browser heruntergeladen, den die Bibliothek verwenden wird.

Scrapen einer statischen Website  

Wie alle Web-Scraping-Tools können Sie mit Puppeteer den HTML-Code von Websites scrapen.

Im Folgenden werden die Schritte beschrieben, die Sie ausführen sollten, um mit Puppeteer die erste Seite der Beiträge des Blogs von Bright Data zu scrapen:

Erstellen Sie die Datei index.js und importieren Sie Puppeteer:

const puppeteer = require('puppeteer');

Fügen Sie dann die für die Ausführung von Puppeteer erforderliche Boilerplate ein:

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://brightdata.com/blog');

  // all the web scraping will happen here  

  await browser.close();

})();

Diese Funktion öffnet einen Browser, navigiert zu der Seite, um sie zu scrapen, und schließt den Browser wieder.

Alles, was noch zu tun ist, ist, die Daten von der Seite zu scrapen.

In Puppeteer greifen Sie am einfachsten mit der Methode page.evaluate auf HTML-Daten zu. Puppeteer verfügt zwar über die Methoden $ und $$, die als Wrapper für das Abrufen von Elementen nützlich sind, es ist aber leichter, einfach alle Daten von page.evaluate abzurufen.

Im Blog von Bright Data sind alle Daten der Beiträge von Tags <a> mit der Klasse brd_post_entry umgeben. Der Titel des Beitrags befindet sich in einem Element <h3> mit der Klasse brd_post_title. Der Link zum Beitrag ist der Wert href von brd_post_entry.

Hier sehen Sie, wie die Funktion page.evaluate, die diese Werte extrahiert, aussieht:

  const data = await page.evaluate( () => {

    let data = [];
    const titles = document.querySelectorAll('.brd_post_entry');

    for (const title of titles) {
      const titleText = title.querySelector('.brd_post_title').textContent;
      const titleLink = title.href;

      const article = { title: titleText, link: titleLink };
      data.push(article);
    }

    return data;

  })

Schließlich können Sie die Daten auf der Konsole ausgeben:

  console.log(data);

Das vollständige Skript sieht wie folgt aus:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://brightdata.com/blog');

  const data = await page.evaluate(() => {

    let data = [];
    const titles = document.querySelectorAll('.brd_post_entry');

    for (const title of titles) {
      const titleText = title.querySelector('.brd_post_title').textContent;
      const titleLink = title.href;

      const article = { title: titleText, link: titleLink };
      data.push(article);
    }

    return data;

  })

  console.log(data);

  await browser.close();

})();

Führen Sie es aus, indem Sie node index.js auf Ihrem Gerät aufrufen. Das Skript sollte eine Liste mit den Titeln der Beiträge und Links zurückgeben:

[
  {
    title: 'APIs for Dummies: Learning About APIs',
    link: 'https://brightdata.com/blog/web-data/apis-for-dummies'
  },
  {
    title: 'Guide to Using cURL with Python',
    link: 'https://brightdata.com/blog/how-tos/curl-with-python'
  },
  {
    title: 'Guide to Scraping Walmart',
    link: 'https://brightdata.com/blog/how-tos/guide-to-scraping-walmart'
  },
…

Scrapen dynamischer Inhalte  

Das Scrapen statischer Inhalte ist eine einfache Aufgabe, die mit unkomplizierten Tools leicht erledigt werden kann. Glücklicherweise kann Puppeteer für eine Vielzahl von Aktionen verwendet werden, wie z. B. Klicken, Tippen und Scrollen. Sie können alle diese Aktionen nutzen, um mit dynamischen Seiten zu interagieren und Benutzeraktionen zu simulieren.

Eine typische Web-Scraping-Aufgabe mit einer Bibliothek wie dieser wäre die Suche nach einem bestimmten Datensatz auf der Website. Sie könnten zum Beispiel mit Puppeteer nach allen Beiträgen über Puppeteer, die auf der Website von Bright Data veröffentlicht sind, suchen.

Tun Sie das folgendermaßen:

Schritt 1: Cookies akzeptieren

 

Wenn jemand den Blog von Bright Data besucht, erscheint manchmal ein Cookie-Banner:

Klicken Sie auf die Schaltfläche Alle akzeptieren mit folgendem Code:  

  await page.waitForSelector('#brd_cookies_bar_accept', {timeout: 5000})
    .then(element => element.click())
    .catch(error => console.log(error));

Die erste Zeile des Codes wartet auf ein Element mit #brd_cookies_bar_accept, das fünf Sekunden lang angezeigt wird. Die zweite Zeile klickt auf dieses Element. Die dritte Zeile sorgt dafür, dass das Skript nicht abstürzt, wenn die Cookie-Leiste nicht erscheint.

Beachten Sie, dass Sie in Puppeteer „warten“ festlegen, indem Sie eine Bedingung eingeben, auf die Sie warten wollen. Sie legen also keine bestimmte Wartezeit fest, nach der die vorherige Aktion ausgeführt werden soll. Ersteres wird als implizites Warten, letzteres als explizites Warten bezeichnet.

Von explizitem Warten in Puppeteer wird dringend abgeraten, da es zu Problemen bei der Ausführung kommen kann. Wenn Sie eine explizite Wartezeit angeben, ist diese entweder zu lang (was ineffizient ist) oder zu kurz (was bedeutet, dass das Skript nicht korrekt ausgeführt wird).

Schritt 2: Suche nach Beiträgen

 

Danach muss das Skript auf das Suchsymbol klicken. Geben Sie „Puppeteer“ ein und klicken Sie erneut auf das Suchsymbol, um eine Suche auszulösen:

Das können Sie mit folgendem Code tun:


await page.click('.search_icon');

  await page.waitForSelector('.search_container.active');
  const search_form = await page.waitForSelector('#blog_search');
  await search_form.type('puppeteer');

 await page.click('.search_icon');

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

Dieses Beispiel funktioniert ähnlich wie das Beispiel mit dem Cookie-Banner. Nach dem Anklicken der Schaltfläche müssen Sie warten, bis der Suchcontainer erscheint. Deshalb wartet der Code auf ein Element, das dem CSS-Selektor .suche_container.aktiv entspricht.

Schließlich müssen Sie eine Pause von zwei Sekunden hinzufügen, bis die Elemente geladen sind. Zwar wird in Puppeteer von expliziten Wartezeiten abgeraten, doch gibt es zurzeit für diesen Fall keine anderen geeigneten Optionen.

Bei den meisten Websites können Sie bei einer Änderung der URL die Methode waitForNavigation verwenden. Wenn ein neues Element erscheint, können Sie die Methode waitForSelector benutzen. Herauszufinden, ob einige Elemente aktualisiert werden, ist etwas schwieriger und würde den Rahmen dieses Artikels sprengen.

Wenn Sie es dennoch versuchen möchten, kann Ihnen diese Stack Overflow-Antwort helfen.

Schritt 3: Erfassen der Beiträge

 

Nachdem Sie nach den Beiträgen gesucht haben, können Sie den Code verwenden, den Sie bereits für das Scrapen statischer Seiten verwendet haben, um die Titel der Beiträge des Blogs zu erhalten:

  const data = await page.evaluate( () => {

    let data = [];
    const titles = document.querySelectorAll('.brd_post_entry');

    for (const title of titles) {
      const titleText = title.querySelector('.brd_post_title').textContent;
      const titleLink = title.href;

      const article = { title: titleText, link: titleLink };
      data.push(article);
    }

    return data;

  })

  console.log(data);

Hier ist der vollständige Code für das Skript:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://brightdata.com/blog');

  const cookie_bar_accept = await page.waitForSelector('#brd_cookies_bar_accept');
  await cookie_bar_accept.click();
  await new Promise(r => setTimeout(r, 500));

  await page.click('.search_icon');

  await page.waitForSelector('.search_container.active');
  const search_form = await page.waitForSelector('#blog_search');
  await search_form.type('puppeteer');

  await page.click('.search_icon');

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

  const data = await page.evaluate( () => {

    let data = [];
    const titles = document.querySelectorAll('.brd_post_entry');

    for (const title of titles) {
      const titleText = title.querySelector('.brd_post_title').textContent;
      const titleLink = title.href;

      const article = { title: titleText, link: titleLink };
      data.push(article);
    }

    return data;

  })

  console.log(data);

  await browser.close();

})();

Können Sie es besser?  

Skripte für das Web Scraping sind mit Puppeteer zwar möglich, aber nicht optimal. Puppeteer wurde für die Automatisierung von Tests entwickelt, weshalb es für das Web Scraping eher ungünstig ist.

Wenn es Ihnen bei Ihren Skripten zum Beispiel um Skalierbarkeit und Effizienz geht, ist es wichtig, dass Sie scrapen können, ohne blockiert zu werden. Zu diesem Zweck können Sie Proxys verwenden – Gateways zwischen Ihnen und der Website, die Sie scrapen. Obwohl Puppeteer die Verwendung von Proxys unterstützt, müssen Sie ein Proxy-Netzwerk finden und mit diesem selbst einen Vertrag abschließen (Erfahren Sie mehr über die Puppeteer Proxy Integration mit Bright Data).  

Außerdem ist es nicht einfach, Puppeteer für den parallelen Einsatz zu optimieren. Wenn Sie viele Daten scrapen wollen, müssen Sie hart arbeiten, um eine optimale Leistung zu erzielen.

Diese Nachteile bedeuten, dass Puppeteer eine gute Wahl für kleine Skripte für den Hobbygebrauch ist, aber wenn Sie es verwenden, werden Sie eine Menge Zeit investieren, um Ihre Vorgänge zu skalieren.

Wenn Sie nach etwas Ausschau halten, das einfacher zu verwenden ist, sollten Sie sich für eine Webdatenplattform wie Bright Data entscheiden. Sie ermöglicht es Unternehmen, riesige Mengen strukturierter Daten aus dem Internet zu erfassen, da sie einfach zu bedienende Tools verwendet, wie den Scraping-Browser (kompatibel mit Puppeteer/Playwright), der speziell für das Web Scraping entwickelt wurde.  

Fazit

In diesem Artikel haben Sie gelernt, wie Sie Puppeteer für das Scraping statischer und dynamischer Websites verwenden können.

Puppeteer kann die meisten Aktionen eines Browsers ausführen, z. B. das Anklicken von Elementen, die Eingabe von Text und die Ausführung von JavaScript. Und dank der Verwendung impliziter Wartezeiten lassen sich Skripte mit Puppeteer schnell und einfach schreiben.

Aber es kann auch Probleme geben, denn Puppeteer ist nicht das effizienteste Tool für das Web-Scraping, und die Dokumentation ist für Einsteiger eher ungeeignet. Es ist auch schwierig, Scraping-Aktivitäten mit Puppeteer zu skalieren, wenn Sie nicht bereits über Erfahrungen damit verfügen.

Sind Sie es leid, selbst Daten zu erfassen? Holen Sie sich bereits erfasste oder maßgeschneiderte Datensätze!