Die Aufgabe ist eigentlich einfach: Der Kunde will mehrere Websites durchsuchbar machen, d.h. man klickt auf „Suche“ und bekommt Treffer für alle seine Unterseiten ausgespielt. Problem dabei: Es ist nicht einfach, weil die meisten Indexer für CMS nur die Suche auf der eigenen Seite erlauben. Deshalb muss eine externe Lösung her!

Wer das Ganze einfach haben will, nimmt Google. Will man z.B. auf drei Seiten den Begriff „schraubverschluss“ suchen übergibt man der Suche:

Das ist schnell, einfach, aber natürlich nicht besonders schön, zumla externe Adwords oben erscheinen können usw.

Ich habe etwas recherchiert und bin auf scrapy gestoßen, der einmal relativ leicht zu installieren und außerdem über Python relativ leicht anpassbar ist. Man braucht dazu allerdings Grundkenntnisse in Python. Ich stelle hier mal eine einfache Lösung vor.

Installation scrapy und Solr

scrapy ist ein Crawler, d.h. das Programm kann Seiten aufrufen und Inhalte daraus extrahieren. Solr ist ein Suchserver. Eine Verbindung zwischen beiden ist praktisch, weil Solr die Inhalte von Scrapy übernehmen kann und so die Suche beinahe fertig ist. Außerdem ist die Lösung einfach anzupassen und relativ schnell realisierbar.

Zunächst die Installation der beiden Programme. Ich verwende Ubuntu, die Installation auf anderen Linux-Systemen sollte ähnlich sein, auf dem Mac hilft die Installation des Java-SDK 8 sowie homebrew für scrapy weiter. Unter Windows kann man ebenfalls Python und Java installieren und die Software so zum Laufen bekommen. Die Installation von Scrapy ist hier allgemein dokumentiert. Solr benötigt eine Java Runtime und das Solr-Paket. Außerdem sollte man wissen, wie man auf der Kommandozeile Javaprogramme ausführt 😉

Die Vorbereitung in Ubuntu (16.04 oder später):

Danach kann man per pip (Python installs Python) scrapy herunterladen und installieren:

Das dauert ein bis zwei Minuten auf einem modernen Rechner, dann ist scrapy installiert.

Solr laden wir herunter, entpacken das Archiv und richten einen schöneren Link ein:

Das Starten von Solr und das Erstellen einer Collection (also einer Suchdatenbank) ist denkbar einfach:

Danach können wir per Browser schon auf den Port 8983 zugreifen, um auf Solr zu arbeiten. Auf der lokalen Maschine wäre das also http://localhost:8938/.

Scrapy-Projekt erstellen

Das Scrapy-Projekt erstellen wir ebenfalls per Kommandozeile:

Mit dieser Basis-Einstellung kann man bereits schon die Homepage abfragen:

Das ist im Moment noch relativ langweilig, weil nur eine Website aufgerufen wird. Wir würden ja gerne die gesamte Website crawlen und die Daten in Solr ablegen. Dazu legen wir zunächst fest, welche Daten wir erheben wollen. Das machen wir anhand eines Beispiels, nämlich von der Seite auxnet.de die Blogbeiträge auszulesen und in Solr zu speichern.  Dazu ändern wie die Datei meincrawler/items.py:

Es werden also vier Felder festgelegt: Der Titel, die Url, der Text des Beitrags und sein Datum.

Als nächstes müssen wir die oben angelegte Spider entsprechend dressieren, so dass sie die Daten aus der Seite extrahiert und auch Links folgt. Die geänderte Datei ist meincrawler/spiders/auxnet.py:

Hier passiert die Hauptarbeit von Scrapy. Scrapy beginnt zunächst auf der Homepage (oben festgelegt) und ruft dann für diese Seite parse auf:

  • Zunächst wird geprüft, ob die Seite bereits im lokalen URL-Cache (seen) ist. Damit werden Seiten nicht mehrfach aufgerufen.
  • Danach wird geprüft, ob es sich bei der Seite um eine Beitragsseite handelt. Das können wir per xpath machen, indem wir testen ob der body-Tag der Seite die Klasse single-post aufweist.
  • Ist das der Fall, können wir per xpath die Elemente der Seite extrahieren:
    • Der Title steht in einem H1-Tag
    • Die URL bekommen wir über die Response des Servers
    • Der Text kann aus dem Sektion des Posts geholt werden, wobei wir den Text als Array bekommen uns erst per join zusammenführen.
    • Das Datum steht in einem Attribut. Auch das kann xpath einfach bewerkstelligen.
  • Damit ist das Item fertig. Was wir damit machen, sehen wir im nächsten Skript.
  • Dennoch sind wir nicht ganz fertig. Am Ende Suchen wir alle Links und folgen ihnen, falls wir den Link noch nicht gesehen haben.

Das Skript läuft damit bereits schon und extrahiert die Daten korrekt. Allerdings landen sie noch nirgendwo. Scrapy nutzt Pipelines dafür, die sehr einfach einzurichten sind.

Um die Pipeline zu aktivieren, ändern wir eine Zeile in der Datei settings.py:

Die Zeilen sollten bereits in der Datei sein, man muss sie nur noch einkommentieren.

Damit ist die Pipelineklasse aktiviert, die wir nur noch schreiben müssen. Die Datei ist pipelines.py:

Das speichern in Solr ist also sehr einfach. Die Pipeline wird nach jedem Item aufgerufen und man muss lediglich die entsprechenden Solr-Felder befüllen. In unserem Fall nutzen wir die „magic fields“ von Solr, die per Endung am Feldschlüssel definieren, welchen Dateitypen sie besitzen.

Im Solr-Query (z.B. auf http://localhost:8983/solr/#/collection1/query) kann man nun die Datenbank durchsuchen.

Man sieht in dem kleinen Beispiel bereits, dass es sehr einfach ist, per Scrapy komplexe Daten aus Websites zu extrahieren und z.B. in Solr zu speichern. Denkbar wären noch diverse Erweiterungen, die ich in diesem Post nicht weiter ausführen will:

  • Alte Beiträge löschen (z.B. durch Leeren des Solr-Index am Anfang oder einen Zeitstempel, der klar macht, dass bestimmte Datensätze im letzten Scrapy-Lauf nicht mehr vorgekommen sind).
  • Kommentarfelder ebenfalls in den Solr übernehmen.
  • Metadaten wie Tags im Solr speichern.
  • Suchmaske, welche die Solr-Daten ausliest und schön darstellt (z.B. in PHP).