Es kommt immer wieder mal vor das wir Daten sammeln und auswerten möchten – sei es für den Job oder Privat. Aber wie macht man das am besten? Niemand möchte diesen Vorgang manuell erledigen – denn das kostet viel Zeit und nerven. Auftritt Crawler!

Dieser Artikel ist für die Fälle gedacht, in denen man keine API oder Feed zur Verfügung hat.

Denn genau dann kommt ein „Crawler“ zum Einsatz. Als Crawler bezeichnet man klassischerweise ein Skript das automatisiert Dokumente im Netz findet und/oder verarbeitet. In unserem Fall sind das Webseiten.

Nehmen wir als Beispiel den Blog https://web-developer-blog.com und versuchen alle Tags aller Postings herauszufinden.

Wir benutzen das folgende Muster um über alle Seiten zu navigieren: https://web-developer-blog.com/page/{page}. Das lässt sich prima in einer Schleife durchlaufen!

Praktisches Crawler Beispiel

Natürlich möchte ich euch auch zeigen wie so etwas in Code aussehen könnte. Ich benutze hierzu lediglich zwei Symfony Komponenten: CSS-Selector und DOM-Crawler.

composer req symfony/css-selector symfony/dom-crawler

Eigentlich benötigen wir nur den DOM-Crawler, die CSS-Selector Komponente verwenden wir aus Bequemlichkeit. Diese erlaubt uns nämlich das DOM mittels CSS-Selektoren zu navigieren.

Aber kommen wir zum eigentlichen Skript:

<?php

use Symfony\Component\DomCrawler\Crawler;

require_once __DIR__ . '/vendor/autoload.php';

$page = 1;

while (true) {
    $html = file_get_contents('https://web-developer-blog.com/page/' . $page);

    echo 'Parsing page ' . $page . PHP_EOL;

    (new Crawler($html))
        ->filter('h1.entry-title')
        ->each(function(Crawler $headline) {
            echo 'Post "' . $headline->text() . '"' . PHP_EOL;

            $postingHtml = file_get_contents($headline->filter('a')->attr('href'));

            $tags = (new Crawler($postingHtml))
                ->filter('.tags-links a')
                ->extract(['_text']);

            echo 'Tags: ' . implode(', ', $tags) . PHP_EOL . PHP_EOL;
        });

    $page++;
}

Gehen wir das Ganze mal durch… In einer Endlosschleife holen wir uns mittels file_get_contents() jede Seite mit Postings – eine Library wie „Guzzle“ wäre hier sicherlich eleganter, aber es handelt sich schließlich um ein Beispiel 😉

In den nächsten Zeilen füttern wir unser HTML an den Crawler und filtern nun mittels CSS-Selektoren nach den Artikel-Überschriften, denn diese beinhalten den Link zum Artikel.

Im Callback der each Methode erhalten wir nun das Ergebnis des Filters als Parameter und holen uns den Titel und die URL des Postings. Diese URL verwenden wir direkt weiter und holen uns die Tags von der Posting Seite.

Führen wir das Skript in der Konsole aus, erhalten wir folgende Ausgabe:

Parsing page 1
Post "Balkendiagramm mit D3"
Tags: API, D3, Daten, HTML5, Javascript, SVG

Post "D3 Javascript Bibliothek"
Tags: API, D3, Daten, Framework, HTML5, Javascript

Post "HTML5 Gamepad API"
Tags: API, Gamepad, HTML5, Javascript, MooTools, plain

Post "Bootstrap v4 manuell kompilieren – UPDATE"
Tags: Bootstrap, CSS, HTML5, PHP, Sass

Post "Konfigurationsobjekte vs Arrays"
Tags: Design-Pattern, Framework, PHP, Usability

Post "PHP Konferenz 2016 in München"
Tags: Design-Pattern, Hash, Performance, PHP, PHP 7, Sicherheit, symfony, XSS

Post "Wie man ein Singleton via Trait definiert"
Tags: Basics, Design-Pattern, PHP, PHP 5.4, plain, Snippets, Tutorial

Post "Der Wix Homepage Baukasten"
Tags: CMS, Performance, Plugin, Responsive, SEO, Usability

Post "Basics Tutorial: Composer unter Windows (und Linux)"
Tags: Basics, Framework, GIT, JSON, PHP, Tools, Tutorial

Post "Die Gefahr der dynamischen includes"
Tags: Basics, CMS, Daten, Framework, PHP, plain, Sicherheit

Parsing page 2
Post "PHP 7 – Neue Features und Funktionen (2/2)"
Tags: Performance, PHP, PHP 5.6, PHP 7

Post "PHP 7 – Neue Features und Funktionen (1/2)"
Tags: Performance, PHP, PHP 5.6, PHP 7

Post "SVG vs. Icon Font"
...

Und genau so kann man nun relativ einfach anfangen Daten von Webseiten zu sammeln. Ich habe in der Vergangenheit ähnliche Skripte verwendet um die Luftqualität oder Pollenbelastung von Düsseldorf auszulesen.

Theoretisch kann man mit einem solchen Skript und einem Cronjob auch die Preisentwicklung von Produkten diverser Online-Shops verfolgen – oder sich einen persönlichen Preis-Alarm programmieren 😉

Für all diese Anwendungsbereiche benötigen wir nur die entsprechenden CSS-Selektoren, die wir uns direkt im Browser (mittels Entwickler-Toolbar) ansehen können.

Lasst eurer Kreativität freien Lauf und schreibt mir in die Kommentare was ihr für Crawler/Parser gebaut habt. Ich wünsche euch eine angenehme Woche, bleibt gesund!

Bis zum nächsten Mal wünsche ich euch Happy Coding!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.