Wie verwende ich Scrapy mit der Django-Anwendung?

Es gibt einige Artikel darüber, wie man Scrapy in eine Django-Anwendung integriert (oder umgekehrt?). Die meisten von ihnen behandeln jedoch kein vollständiges Beispiel, das das Auslösen von Spinnen aus Django-Ansichten einschließt. Da es sich um eine Webanwendung handelt, muss dies unser Hauptziel sein.

Was brauchen wir?

Bevor wir anfangen, ist es besser zu spezifizieren, was wir wollen und wie wir es wollen. Überprüfen Sie dieses Diagramm:

Es zeigt, wie unsere App funktionieren sollte:

  • Der Client sendet eine Anforderung mit einer URL, um sie zu crawlen. (1)
  • Django veranlasst Scrapy, eine Spinne zu starten, um diese URL zu crawlen. (2)
  • Django gibt eine Antwort zurück, um Client mitzuteilen, dass das Crawlen gerade begonnen hat. (3)
  • Scrapy führt das Crawlen durch und speichert die extrahierten Daten in einer Datenbank. (4)
  • Django holt diese Daten aus der Datenbank und gibt sie an den Client zurück. (5)

Sieht soweit gut und einfach aus.

Eine Anmerkung zu dieser 5. Aussage

Django holt diese Daten aus der Datenbank und gibt sie an den Client zurück. (5)

Weder Django noch der Kunde wissen nicht, wann Scrapy das Crawling abgeschlossen hat. Es gibt eine Rückrufmethode namens pipeline_closed, die jedoch zum Scrapy-Projekt gehört. Es kann keine Antwort von Scrapy-Pipelines zurückgegeben werden. Wir verwenden diese Methode nur, um extrahierte Daten in einer Datenbank zu speichern.

Irgendwann müssen wir dem Kunden sagen:

Hallo! Crawling abgeschlossen und ich sende Ihnen hier gecrawlte Daten.

Hierfür gibt es zwei Möglichkeiten (Bitte kommentieren Sie, wenn Sie mehr entdecken):

Wir können entweder Web-Sockets verwenden, um den Client zu informieren, wenn das Crawlen abgeschlossen ist.

Oder,

Wir können alle 2 Sekunden (mehr oder weniger) Anforderungen vom Client senden, um den Crawling-Status zu überprüfen, nachdem wir die Antwort "Crawling gestartet" erhalten haben.

Die Web Socket-Lösung klingt stabiler und robuster. Es erfordert jedoch einen zweiten Dienst, der separat ausgeführt wird, und bedeutet mehr Konfiguration. Ich werde diese Option vorerst überspringen. Aber ich würde Web-Sockets für meine Anwendungen auf Produktionsebene auswählen.

Schreiben wir einen Code

Es ist Zeit, echte Arbeit zu leisten. Beginnen wir mit der Vorbereitung unserer Umwelt.

Abhängigkeiten installieren

Erstellen Sie eine virtuelle Umgebung und aktivieren Sie sie:

$ python3.5 -m venv venv
$ source venv / bin / activate

Installieren Sie dann die erforderlichen Abhängigkeiten mit:

$ pip installiere django scrapy scrapyd python-scrapyd-api

Scrapyd ist ein Daemon-Dienst zum Ausführen von Scrapy-Spinnen. Sie können die Details hier entdecken.

python-scrapyd-api ist ein Wrapper, mit dem wir über unser Python-Programm scrapyd sprechen können.

Hinweis: Ich werde Python 3.5 für dieses Projekt verwenden.

Erstellen eines Django-Projekts

Erstelle ein Django-Projekt mit einer App namens main:

$ django-admin startproject iCrawler
$ cd iCrawler && python manage.py startapp main

Wir brauchen auch ein Modell, um unsere verkratzten Daten zu speichern. Machen wir es uns einfach:

Fügen Sie die Haupt-App in INSTALLED_APPS in settings.py hinzu und als letzten Schritt Migrationen:

$ python manage.py makemigrations
$ python manage.py migrieren

Fügen wir unserer Haupt-App eine Ansicht und eine URL hinzu:

Ich habe versucht, den Code so gut wie möglich zu dokumentieren.

Der Haupttrick ist jedoch unique_id. Normalerweise speichern wir ein Objekt in einer Datenbank und erhalten dann dessen ID. In unserem Fall geben wir die unique_id an, bevor wir sie erstellen. Sobald das Crawlen abgeschlossen ist, fragt der Client nach den gecrawlten Daten. Mit dieser unique_id können wir eine Abfrage erstellen und Ergebnisse abrufen.

Und eine URL für diese Ansicht:

Scrapy-Projekt erstellen

Es ist besser, wenn wir das Scrapy-Projekt unter (oder neben) unserem Django-Projekt erstellen. Dies macht es einfacher, sie miteinander zu verbinden. Also erstellen wir es im Django-Projektordner:

$ cd iCrawler
$ scrapy Startprojekt scrapy_app

Jetzt müssen wir unsere erste Spinne aus dem Ordner scrapy_app erstellen:

$ cd scrapy_app
$ scrapy genspider -t crawle icrawler https://google.com

Ich nenne Spinne als Icrawler. Sie können es als alles benennen. Schau -t Teil kriechen. Wir geben eine Basisvorlage für unsere Spinne an. Sie können alle verfügbaren Vorlagen anzeigen mit:

$ scrapy genspider -l
Verfügbare Vorlagen:
Basic
kriechen
csvfeed
xmlfeed

Jetzt sollten wir eine Ordnerstruktur wie diese haben:

Anschließen von Scrapy an Django

Um von Scrapy aus auf Django-Modelle zugreifen zu können, müssen diese miteinander verbunden werden. Gehen Sie zur Datei settings.py unter scrapy_app / scrapy_app / und geben Sie Folgendes ein:

Das ist es. Beginnen wir nun mit scrapyd, um sicherzustellen, dass alles richtig installiert und konfiguriert ist. In scrapy_app / Ordner ausführen:

$ scrapyd

Dadurch wird scrapyd gestartet und einige Ausgaben generiert. Scrapyd hat auch eine sehr minimale und einfache Webkonsole. Wir brauchen es nicht für die Produktion, aber wir können es verwenden, um aktive Jobs während der Entwicklung zu beobachten. Sobald Sie scrapyd gestartet haben, rufen Sie http://127.0.0.1:6800 auf und prüfen Sie, ob es funktioniert.

Konfigurieren unseres Scrapy-Projekts

Da es in diesem Beitrag nicht um Grundlagen des Scrapy geht, überspringe ich den Teil über das Modifizieren von Spinnen. Sie können Ihre Spinne mit offiziellen Unterlagen erstellen. Ich werde hier jedoch meine Beispielspinne platzieren:

Oben ist die Datei icrawler.py aus scrapy_app / scrapy_app / spiders. Aufmerksamkeit auf __init__ Methode. Es ist wichtig. Wenn wir eine Methode oder Eigenschaft dynamisch machen wollen, müssen wir sie unter der Methode __init__ definieren, damit wir Argumente von Django übergeben und sie hier verwenden können.

Wir müssen auch eine Item-Pipeline für unser Scrapy-Projekt erstellen. Eine Pipeline ist eine Klasse zum Ausführen von Aktionen für überarbeitete Elemente. Aus der Dokumentation:

Typische Verwendungen von Artikel-Pipelines sind:
  • Bereinigen von HTML-Daten
  • Überprüfung der gelöschten Daten (Überprüfung, ob die Elemente bestimmte Felder enthalten)
  • nach Duplikaten suchen (und diese löschen)
  • Speichern des abgekratzten Gegenstands in einer Datenbank

Yay! Speichern des abgekratzten Elements in einer Datenbank. Jetzt erstellen wir eine. Im Ordner scrapy_project befindet sich bereits eine Datei mit dem Namen pipelines.py. Außerdem enthält diese Datei eine leere, aber einsatzbereite Pipeline. Wir müssen es nur ein wenig modifizieren:

Und als letzten Schritt müssen wir diese Pipeline in der scrapy settings.py-Datei aktivieren (auskommentieren):

# Konfigurieren Sie Element-Pipelines
# Siehe http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    'scrapy_app.pipelines.ScrapyAppPipeline': 300,
}
Vergessen Sie nicht, scraypd neu zu starten, wenn es funktioniert.

Dieses Scrapy-Projekt im Grunde,

  • Crawlt eine Website (kommt aus Django-Sicht)
  • Extrahieren Sie alle URLs von der Website
  • Schreiben Sie sie in eine Liste
  • Speichern Sie die Liste in der Datenbank über Django-Modelle.

Und das ist alles für den Back-End-Teil. Django und Scrapy sind beide integriert und sollten gut funktionieren.

Hinweise zum Frontend-Teil

Nun, dieser Teil ist so subjektiv. Wir haben jede Menge Möglichkeiten. Persönlich habe ich mein Frontend mit React aufgebaut. Der einzige Teil, der nicht subjektiv ist, ist die Verwendung von setInterval. Ja, denken wir an unsere Optionen: Web-Sockets und Senden von Anfragen an den Server alle X Sekunden.

Zur Verdeutlichung der Grundlogik ist dies eine vereinfachte Version meiner React Component:

Sie können die Details anhand der von mir hinzugefügten Kommentare herausfinden. Es ist eigentlich ganz einfach.

Oh, das ist es. Es hat länger gedauert als ich erwartet hatte. Bitte hinterlassen Sie einen Kommentar für jede Art von Feedback.

Beispielprojekte

Im Folgenden finden Sie einige Beispielimplementierungen, die auf diesem Artikel basieren. Wenn Sie eine haben, erwähnen Sie diese bitte als Kommentar. Ich werde diesen Abschnitt weiter aktualisieren.

Dies ist eine schöne Vorlagen-App von Adrian Castellanos Zaragoza:

-

Dies von 심명훈 und beinhaltet auch den Frontend-Teil mit einfachem Javascript. Überprüfen Sie dies heraus!

-