Zurück zum Blog
Anleitungen
Raluca PenciucLast updated on Mar 31, 20267 min read

Webscraping mit Cheerio: So sammeln Sie ganz einfach Daten von Webseiten

Webscraping mit Cheerio: So sammeln Sie ganz einfach Daten von Webseiten

Längst vorbei sind die Zeiten, in denen Sie die Daten, die Ihnen beim Start Ihrer Projekte halfen, manuell gesammelt und verarbeitet haben. Ob E-Commerce-Website oder Algorithmus zur Lead-Generierung – eines ist sicher: Der Prozess der Datenerfassung war mühsam und zeitaufwendig.

In diesem Artikel erfahren Sie, wie Cheerio Ihnen mit seinen umfangreichen Funktionen zum Parsen von Markup-Sprachen helfen kann – zunächst anhand einiger einfacher Beispiele und anschließend anhand eines Anwendungsfalls aus der Praxis.

Einführung in Cheerio

„Aber was ist Cheerio?“, fragen Sie sich vielleicht. Nun, um ein weit verbreitetes Missverständnis auszuräumen, beginne ich damit, was Cheerio nicht ist: ein Browser.

Die Verwirrung rührt möglicherweise daher, dass Cheerio Dokumente in einer Markup-Sprache parst und anschließend eine API bereitstellt, mit der Sie die resultierende Datenstruktur bearbeiten können. Im Gegensatz zu einem Browser rendert Cheerio das Dokument jedoch nicht visuell, lädt keine CSS-Dateien und führt kein JavaScript aus.

Im Grunde genommen empfängt Cheerio also eine HTML- oder XML-Eingabe, analysiert die Zeichenkette und gibt die API zurück. Das macht es unglaublich schnell und benutzerfreundlich, weshalb es bei Node.js-Entwicklern so beliebt ist.

Einrichten der Umgebung

Sehen wir uns nun einige praktische Beispiele dafür an, was Cheerio leisten kann. Zunächst einmal müssen Sie sicherstellen, dass Ihre Umgebung vollständig eingerichtet ist.

Es versteht sich von selbst, dass Node.js auf deinem Rechner installiert sein muss. Falls nicht, folge einfach den Anweisungen auf der offiziellen Website, entsprechend deinem Betriebssystem.

Achten Sie darauf, die Long Term Support-Version (LTS) herunterzuladen, und vergessen Sie nicht den Node.js Package Manager (NPM). Mit diesen Befehlen können Sie überprüfen, ob die Installation erfolgreich war:

node -v
npm -v

Die Ausgabe sollte wie folgt aussehen:

Nun zur IDE-Frage: Für dieses Tutorial werde ich Visual Studio Code verwenden, da es sehr flexibel und benutzerfreundlich ist, aber du kannst natürlich jede IDE verwenden, die du bevorzugst.

Erstellen Sie einfach einen Ordner für Ihr kleines Projekt und öffnen Sie ein Terminal. Führen Sie den folgenden Befehl aus, um ein Node.js-Projekt einzurichten:

npm init -y

Dadurch wird eine Standardversion der Datei „package.json“ erstellt, die jederzeit geändert werden kann.

Nächster Schritt: Ich werde TypeScript zusammen mit den Typdefinitionen für Node.js installieren:

npm install typescript @types/node -save-dev

Ich habe mich in diesem Tutorial für TypeScript entschieden, da es eine optionale statische Typisierung für JavaScript-Objekte bietet, was den Code widerstandsfähiger gegen Typfehler macht. 

Dies ist derselbe Vorteil, der laut einer aktuellen CircleCI-Umfrage zu den beliebtesten Programmiersprachen zu einer stetig wachsenden Beliebtheit in der JavaScript-Community geführt hat.

Um die korrekte Installation des vorherigen Befehls zu überprüfen, kannst du Folgendes ausführen:

npx tsc --version

Nun werde ich die Konfigurationsdatei tsconfig.json im Stammverzeichnis des Projektverzeichnisses erstellen, die die Compiler-Optionen definieren soll. Wenn du ein besseres Verständnis dieser Datei und ihrer Eigenschaften erlangen möchtest, hilft dir die offizielle TypeScript-Dokumentation weiter. 

Wenn nicht, kopieren Sie einfach Folgendes und fügen Sie es ein:

{
    "compilerOptions": {
        "module": "commonjs",
        "esModuleInterop": true,
        "target": "es6",
        "moduleResolution": "node",
        "sourceMap": true,
        "outDir": "dist"
    },
    "lib": ["es2015"]
}

Fast fertig! Jetzt müssen Sie (natürlich) Cheerio installieren:

npm install cheerio

Zu guter Letzt erstelle das Verzeichnis „src“, in dem die Code-Dateien gespeichert werden. Apropos Code-Datei: Erstelle die Datei „index.ts“ und lege sie im Verzeichnis „src“ ab.

Wie funktioniert Cheerio?

Perfekt! Jetzt kannst du loslegen.

Zunächst werde ich einige grundlegende Cheerio-Funktionen anhand eines statischen HTML-Dokuments veranschaulichen. Kopiere einfach den folgenden Inhalt und füge ihn in eine neue Datei „static.html“ in deinem Projekt ein:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Page Name - Static HTML Example</title>
</head>
<body>
    <div class="page-heading">
        <h1>Page Heading</h1>
    </div>
    <div class="page-container">
        <div class="page-content">
            <ul>
                <li>
                    <a href="#">Item 1</a>
                      <p class="price">$100</p>
                      <p class="stock">12</p>
                </li>
                <li>
                    <a href="#">Item 2</a>
                    <p class="price">$200</p>
                    <p class="stock">422</p>
                </li>
                <li>
                    <a href="#">Item 3</a>
                    <p class="price">$150</p>
                    <p class="stock">5</p>
                </li>
            </ul>
        </div>
    </div>
    <footer class="page-footer">
        <p>Last Updated: Friday, September 23, 2022</p>
    </footer>
</body>
</html>

Als Nächstes musst du die HTML-Datei als Eingabe an Cheerio übergeben, woraufhin Cheerio die resultierende API zurückgibt:

import fs from 'fs'
import * as cheerio from 'cheerio'

const staticHTML = fs.readFileSync('static.html')
const $ = cheerio.load(staticHTML)

Sollten Sie bei diesem Schritt eine Fehlermeldung erhalten, stellen Sie sicher, dass die Eingabedatei ein gültiges HTML-Dokument enthält, da ab Cheerio-Version 1.0.0 auch dieses Kriterium überprüft wird.

Jetzt können Sie damit beginnen, mit den Möglichkeiten von Cheerio zu experimentieren. Das NPM-Paket ist bekannt für seine jQuery-ähnliche Syntax und die Verwendung von CSS-Selektoren, um die gesuchten Knoten zu extrahieren. In der offiziellen Dokumentation finden Sie weitere Informationen dazu.

Nehmen wir an, Sie möchten den Seitentitel extrahieren:

const title = $('title').text()
console.log("Static HTML page title:", title)

Das sollten wir doch mal testen, oder? Da Sie Typescript verwenden, müssen Sie den Code kompilieren, wodurch das Verzeichnis „dist“ erstellt wird, und anschließend die zugehörige Datei „index.js“ ausführen. Der Einfachheit halber definiere ich das folgende Skript in der Datei „package.json“:

"scripts": {
    "test": "npx tsc && node dist/index.js",
}

Auf diese Weise muss ich lediglich Folgendes ausführen:

npm run test

und das Skript übernimmt beide Schritte, die ich gerade beschrieben habe.

Okay, aber was ist, wenn der Selektor auf mehr als ein HTML-Element passt? Versuchen wir, den Namen und den Aktienkurs der in der ungeordneten Liste aufgeführten Elemente zu extrahieren:

const itemStocks = {}
$('li').each((index, element) => {
    const name = $(element).find('a').text()
    const stock = $(element).find('p.stock').text()
    itemStocks[name] = stock
})
console.log("All items stock:", itemStocks)

Führen Sie nun das Shortcut-Skript erneut aus, und die Ausgabe Ihres Terminals sollte wie folgt aussehen:

Static HTML page title: Page Name - Static HTML Example
All items stock: { 'Item 1': '12', 'Item 2': '422', 'Item 3': '5' }

Anwendungsfälle für Cheerio

Das war also im Grunde nur die Spitze des Eisbergs. Cheerio ist auch in der Lage, XML-Dokumente zu parsen, den Stil der HTML-Elemente zu extrahieren und sogar die Attribute der Knoten zu ändern.

Aber wie kann Cheerio in einem realen Anwendungsfall helfen?

Nehmen wir an, wir möchten einige Daten sammeln, um ein Machine-Learning-Modell für ein zukünftiges größeres Projekt zu trainieren. Normalerweise würdest du bei Google nach Trainingsdateien suchen und diese herunterladen oder die API der Website nutzen.

Aber was tun Sie, wenn Sie keine relevanten Dateien finden können oder die Website, die Sie sich ansehen, keine API bereitstellt, eine Ratenbegrenzung für die Daten hat oder nicht die gesamten Daten anbietet, die Sie auf einer Seite sehen?

Nun, hier kommt Web Scraping ins Spiel. Wenn Sie neugierig auf weitere praktische Anwendungsfälle von Web Scraping sind, können Sie sich diesen gut geschriebenen Artikel aus unserem Blog ansehen.

Zurück zu unserem Thema: Nehmen wir für unser Beispiel einmal an, wir befinden uns genau in dieser Situation: Wir wollen Daten, aber sie sind nirgends zu finden. Denken Sie daran, dass Cheerio weder die HTML-Extraktion noch das Laden von CSS oder die Ausführung von JS übernimmt.

Daher verwende ich in unserem Tutorial Puppeteer, um zur Website zu navigieren, den HTML-Code abzurufen und in einer Datei zu speichern. Anschließend wiederhole ich den Vorgang aus dem vorherigen Abschnitt.

Genauer gesagt möchte ich einige öffentliche Meinungen von Reddit zu einem beliebten Drum-Modul sammeln und die Daten in einer einzigen Datei zusammenfassen, die anschließend in ein potenzielles ML-Trainingsmodell eingespeist wird. Was als Nächstes geschieht, kann variieren: Sentimentanalyse, Marktforschung und vieles mehr.

Anforderung des HTML-Codes

Schauen wir uns an, wie dieser Anwendungsfall in Code umgesetzt wird. Zunächst müssen Sie das Puppeteer-NPM-Paket installieren:

npm install puppeteer

Ich werde außerdem eine neue Datei reddit.ts erstellen, um das Projekt übersichtlicher zu gestalten, und ein neues Skript in der Datei package.json definieren:

"scripts": {
    "test": "npx tsc && node dist/index.js",
    "parse": "npx tsc && node dist/reddit.js"
},

Um das HTML-Dokument abzurufen, definiere ich eine Funktion, die wie folgt aussieht:

import fs from 'fs'
import puppeteer from 'puppeteer'
import * as cheerio from 'cheerio'

async function getContent(url: string): Promise<void> {

    // Open the browser and a new tab
    const browser = await puppeteer.launch()
    const page = await browser.newPage()

    // Navigate to the URL and write the content to file
    await page.goto(url)
    const pageContent = await page.content()
    fs.writeFileSync("reddit.html", pageContent)

    // Close the browser
    await browser.close()
    console.log("Got the HTML. Check the reddit.html file.")
}

Um dies schnell zu testen, fügen Sie einen Einstiegspunkt in Ihren Code ein und rufen Sie die Funktion auf:

async function main() {


    const targetURL = 'https://old.reddit.com/r/Drumming/comments/r3tidc/yamaha_ead10/'
    await getContent(targetURL)
}

main()
    .then(() => {console.log("All done!")})
    .catch(e => {console.log("Unexpected error occurred:", e.message)})

Die Datei reddit.html sollte in Ihrer Projektstruktur erscheinen und das gewünschte HTML-Dokument enthalten.

Wo sind meine Knoten?

Nun kommt ein etwas anspruchsvollerer Teil: Sie müssen die Knoten identifizieren, die für unseren Anwendungsfall von Interesse sind. Kehren Sie zu Ihrem Browser (dem echten) zurück und navigieren Sie zur Ziel-URL. Bewegen Sie den Mauszeiger über den Kommentarbereich, klicken Sie mit der rechten Maustaste und wählen Sie dann die Option „Untersuchen“.

Die Registerkarte „Entwicklertools“ wird geöffnet und zeigt Ihnen genau dasselbe HTML-Dokument an, das Sie zuvor auf Ihrem Rechner gespeichert haben.

Um nur die Kommentare zu extrahieren, müssen Sie die für diesen Abschnitt der Seite spezifischen Selektoren identifizieren. Sie können feststellen, dass sich die gesamte Liste der Kommentare in einem div-Container mit der Klasse „sitable nestedlisting“ befindet.

Genauer betrachtet hat jeder einzelne Kommentar ein Formularelement als übergeordnetes Element mit der Klasse „usertext warn-on-unload“. Unten sehen Sie dann, dass der Text jedes Kommentars auf mehrere p-Elemente aufgeteilt ist.

Parsen und Speichern der Daten

Schauen wir uns an, wie das im Code funktioniert:

function parseComments(): void {

    // Load the HTML document
    const staticHTML = fs.readFileSync('reddit.html')
    const $ = cheerio.load(staticHTML)

    // Get the comments section
    const commentsSection = $('div.sitetable.nestedlisting')

    // Iterate each comment
    const comments = []


    $(commentsSection).find('form.usertext.warn-on-unload').each((index, comment) => {
        let commentText = ""

          // Iterate each comment section and concatenate them
          $(comment).find('p').each((index, piece) => {
            commentText += $(piece).text() + '\n'
          })

          comments.push(commentText)
    })

    // Write the results to external file
    fs.writeFileSync("comments.json", JSON.stringify({comments}))
}

Gut, und nun aktualisieren wir den Einstiegspunkt mit der neu definierten Funktion und sehen uns an, wie dieser Code zusammenwirkt:

async function main() {

    const targetURL = 'https://old.reddit.com/r/Drumming/comments/r3tidc/yamaha_ead10/'
    await getContent(targetURL)
    parseComments()
}

main()
    .then(() => {console.log("All done. Check the comments.csv file.")})
    .catch(e => {console.log("Unexpected error occurred:", e.message)})

Führen Sie den Code mit dem zuvor definierten Skript aus:

npm run parse

Es dauert etwa 5 bis 10 Sekunden, bis sich der Headless-Browser öffnet und zu unserer Ziel-URL navigiert. Wenn Sie neugierig sind, können Sie am Anfang und am Ende jeder unserer Funktionen Zeitstempel hinzufügen, um wirklich zu sehen, wie schnell Cheerio ist.

Die Datei comments.json sollte unser Endergebnis sein:

Dieser Anwendungsfall lässt sich leicht erweitern, um die Anzahl der Upvotes und Downvotes für jeden Kommentar zu analysieren oder die verschachtelten Antworten der Kommentare abzurufen. Die Möglichkeiten sind endlos.

Fazit

Vielen Dank, dass Sie es bis zum Ende dieses Tutorials geschafft haben. Ich hoffe, Sie haben verstanden, wie unverzichtbar Cheerio für den Prozess der Datenextraktion ist und wie Sie es schnell in Ihr nächstes Scraping-Projekt integrieren können.

Wir verwenden Cheerio auch in unserem Produkt, der WebScrapingAPI. Wenn Sie sich jemals mit den vielen Herausforderungen beim Web-Scraping (IP-Sperren, Bot-Erkennung usw.) herumschlagen, sollten Sie es einmal ausprobieren.

Über den Autor
Raluca Penciuc, Full-Stack-Entwickler @ WebScrapingAPI
Raluca PenciucFull-Stack-Entwickler

Raluca Penciuc ist Full-Stack-Entwicklerin bei WebScrapingAPI. Sie entwickelt Scraper, verbessert Umgehungsstrategien und findet zuverlässige Wege, um die Erkennung auf Zielwebsites zu verringern.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.