Ich habe kürzlich Python gelernt und tauche meine Hand in den Aufbau eines Web-Scraper. Es ist überhaupt nichts Besonderes; Der einzige Zweck besteht darin, die Daten von einer Wettwebsite zu entfernen und diese Daten in Excel zu speichern.
Die meisten Probleme sind lösbar und ich habe ein gutes kleines Durcheinander. Ich stoße jedoch in einem Punkt auf eine massive Hürde. Wenn eine Site eine Tabelle mit Pferden lädt und die aktuellen Wettpreise auflistet, befinden sich diese Informationen in keiner Quelldatei. Der Hinweis ist, dass diese Daten manchmal live sind und die Nummern offensichtlich von einem Remote-Server aktualisiert werden. Der HTML-Code auf meinem PC hat einfach eine Lücke, in der die Server alle interessanten Daten durchsuchen, die ich benötige.
Jetzt sind meine Erfahrungen mit dynamischen Webinhalten gering, daher habe ich Probleme, diesen Kopf herumzukriegen.
Ich denke, Java oder Javascript ist ein Schlüssel, der oft auftaucht.
Der Schaber ist einfach eine Quotenvergleichsmaschine. Einige Websites haben APIs, aber ich brauche diese für diejenigen, die dies nicht tun. Ich verwende die Scrapy-Bibliothek mit Python 2.7
Ich entschuldige mich, wenn diese Frage zu offen ist. Kurz gesagt, meine Frage lautet: Wie kann Scrapy verwendet werden, um diese dynamischen Daten zu kratzen, damit ich sie verwenden kann? Damit ich diese Wettquoten-Daten in Echtzeit kratzen kann?
quelle
Firefox
Erweiterungen wiehttpFox
oder ausliveHttpHeaders
und laden Sie eine Seite, die eine Ajax-Anfrage verwendet. Scrapy identifiziert die Ajax-Anforderungen nicht automatisch. Sie müssen manuell nach der entsprechenden Ajax-URL suchen und diese dann anfordern.Antworten:
Webkit-basierte Browser (wie Google Chrome oder Safari) verfügen über integrierte Entwicklertools. In Chrome können Sie es öffnen
Menu->Tools->Developer Tools
. Auf derNetwork
Registerkarte können Sie alle Informationen zu jeder Anfrage und Antwort anzeigen:Im unteren Bereich des Bildes sehen Sie, dass ich die Anfrage bis auf gefiltert habe
XHR
- dies sind Anfragen, die per Javascript-Code gestellt wurden.Tipp: Das Protokoll wird jedes Mal gelöscht, wenn Sie eine Seite laden. Am unteren Rand des Bildes behält die schwarze Punktschaltfläche das Protokoll bei.
Nach der Analyse von Anforderungen und Antworten können Sie diese Anforderungen von Ihrem Webcrawler simulieren und wertvolle Daten extrahieren. In vielen Fällen ist es einfacher, Ihre Daten abzurufen, als HTML zu analysieren, da diese Daten keine Präsentationslogik enthalten und für den Zugriff mit Javascript-Code formatiert sind.
Firefox hat eine ähnliche Erweiterung, heißt es Firebug . Einige werden argumentieren, dass Firebug noch mächtiger ist, aber ich mag die Einfachheit des Webkits.
quelle
Hier ist ein einfaches Beispiel für
scrapy
eine AJAX-Anfrage. Schauen wir uns die Seite rubin-kazan.ru an .Alle Nachrichten werden mit einer AJAX-Anfrage geladen. Mein Ziel ist es, diese Nachrichten mit all ihren Attributen (Autor, Datum, ...) abzurufen:
Wenn ich den Quellcode der Seite analysiere, werden nicht alle diese Nachrichten angezeigt, da die Webseite die AJAX-Technologie verwendet. Aber ich kann mit Firebug von Mozilla Firefox (oder einem gleichwertigen Tool in anderen Browsern) die HTTP-Anforderung analysieren, die die Nachrichten auf der Webseite generiert:
Es wird nicht die gesamte Seite neu geladen, sondern nur die Teile der Seite, die Nachrichten enthalten. Zu diesem Zweck klicke ich unten auf eine beliebige Anzahl von Seiten:
Und ich beobachte die HTTP-Anfrage, die für den Nachrichtentext verantwortlich ist:
Nach Abschluss analysiere ich die Header der Anfrage (ich muss zitieren, dass diese URL von der Quellseite aus dem Abschnitt var extrahiert wird, siehe den folgenden Code):
Und der Formulardateninhalt der Anfrage (die HTTP-Methode ist "Post"):
Und der Inhalt der Antwort, bei der es sich um eine JSON-Datei handelt:
Welches alle Informationen präsentiert, die ich suche.
Von jetzt an muss ich all dieses Wissen in Scrapy umsetzen. Definieren wir die Spinne für diesen Zweck:
In
parse
Funktion habe ich die Antwort auf die erste Anfrage. In habeRubiGuessItem
ich die JSON-Datei mit allen Informationen.quelle
re
Modul (reguläre Ausdrücke), sucht nach der Zeichenfolge'url_list_gb_messages="(.*)"'
und isoliert den Inhalt von Klammern in der gleichnamigen Variablen. Dies ist eine nette Einführung: guru99.com/python-regular-expressions-complete-tutorial.htmlBeim Crawlen treten häufig Probleme auf, bei denen Inhalte, die auf der Seite gerendert werden, mit Javascript generiert werden und Scrapy daher nicht in der Lage ist, danach zu crawlen (z. B. Ajax-Anforderungen, jQuery-Verrücktheit).
Wenn Sie jedoch Scrapy zusammen mit dem Webtest-Framework Selenium verwenden, können wir alles crawlen, was in einem normalen Webbrowser angezeigt wird.
Einige Dinge zu beachten:
Sie müssen die Python-Version von Selenium RC installiert haben, damit dies funktioniert, und Sie müssen Selenium ordnungsgemäß eingerichtet haben. Auch dies ist nur ein Template-Crawler. Man könnte mit Dingen viel verrückter und fortgeschrittener werden, aber ich wollte nur die Grundidee zeigen. Nach dem derzeitigen Stand des Codes werden Sie zwei Anfragen für eine bestimmte URL stellen. Eine Anfrage wird von Scrapy gestellt und die andere von Selen. Ich bin mir sicher, dass es Möglichkeiten gibt, dies zu umgehen, damit Sie Selenium möglicherweise nur dazu bringen können, die einzige Anfrage zu stellen, aber ich habe mich nicht darum gekümmert, dies zu implementieren, und wenn Sie zwei Anfragen ausführen, können Sie die Seite auch mit Scrapy crawlen.
Dies ist sehr leistungsfähig, da Sie jetzt das gesamte gerenderte DOM zum Crawlen zur Verfügung haben und weiterhin alle nützlichen Crawling-Funktionen in Scrapy verwenden können. Dies führt natürlich zu einem langsameren Crawlen, aber je nachdem, wie viel Sie für das gerenderte DOM benötigen, lohnt sich das Warten möglicherweise.
Referenz: http://snipplr.com/view/66998/
quelle
selenium=3.3.1
undpython=2.7.10
, Fehler beim Importieren von Selen aus Selenfrom selenium import webdriver
oderchromedriver
oder was auch immer passieren Sie verwenden werden. Docs EDIT: Dokumentationsreferenz hinzufügen und meine schreckliche Grammatik ändern!Eine andere Lösung wäre die Implementierung eines Download-Handlers oder einer Download-Handler-Middleware. (siehe scrapy docs für weitere Informationen zu Download - Middleware) Nachstehend ist ein Beispiel - Klasse Selen mit Maden PhantomJS WebDriver:
1) Definieren Sie die Klasse im
middlewares.py
Skript.2) In der
JsDownload()
Klasse der VariablenDOWNLOADER_MIDDLEWARE
innerhalbsettings.py
:3) Integriere das
HTMLResponse
Innereyour_spider.py
. Durch Dekodieren des Antwortkörpers erhalten Sie die gewünschte Ausgabe.Optionales Addon:
Ich wollte die Möglichkeit haben, verschiedenen Spinnen mitzuteilen, welche Middleware verwendet werden soll, also habe ich diesen Wrapper implementiert:
Damit der Wrapper funktioniert, müssen alle Spinnen mindestens Folgendes haben:
um eine Middleware einzuschließen:
Vorteil:
Der Hauptvorteil der Implementierung auf diese Weise und nicht in der Spinne besteht darin, dass Sie am Ende nur eine Anfrage stellen. In der Lösung von AT zum Beispiel: Der Download-Handler verarbeitet die Anforderung und gibt dann die Antwort an die Spinne weiter. Die Spinne stellt dann in ihrer Funktion parse_page eine brandneue Anfrage - das sind zwei Anfragen für denselben Inhalt.
quelle
process_requests
,if spider.name in ['spider1', 'spider2']
anstelle des Dekorateurs zu verwendenIch habe eine benutzerdefinierte Downloader-Middleware verwendet, war aber nicht sehr zufrieden damit, da ich es nicht geschafft habe, den Cache damit zum Laufen zu bringen.
Ein besserer Ansatz war die Implementierung eines benutzerdefinierten Download-Handlers.
Es ist ein funktionierendes Beispiel hier . Es sieht aus wie das:
Angenommen, Ihr Schaber heißt "Schaber". Wenn Sie den genannten Code in eine Datei mit dem Namen handlers.py im Stammverzeichnis des Ordners "scraper" einfügen, können Sie Folgendes zu Ihrer settings.py hinzufügen:
Und voilà, das JS analysierte DOM mit Scrapy-Cache, Wiederholungsversuchen usw.
quelle
Ich frage mich, warum niemand die Lösung nur mit Scrapy veröffentlicht hat.
Schauen Sie sich den Blog-Beitrag des Scrapy-Teams SCRAPING INFINITE SCROLLING PAGES an . Das Beispiel verschrottet die Website http://spidyquotes.herokuapp.com/scroll, die unendliches Scrollen verwendet.
Die Idee ist, die Entwicklertools Ihres Browsers zu verwenden und die AJAX-Anforderungen zu beachten. Erstellen Sie dann basierend auf diesen Informationen die Anforderungen für Scrapy .
quelle
Ja, Scrapy kann dynamische Websites verschrotten, Websites, die über JavaScript gerendert werden.
Es gibt zwei Ansätze, um diese Art von Websites zu verschrotten.
Zuerst,
Sie können
splash
Javascript-Code rendern und dann den gerenderten HTML-Code analysieren. Das Dokument und das Projekt finden Sie hier Scrapy Splash, GitZweite,
Wie jeder sagt, können Sie durch Überwachen des
network calls
, ja, den API-Aufruf finden, der die Daten abruft, und den Spott, den der Aufruf in Ihrer Scrapy-Spinne verspottet, um die gewünschten Daten zu erhalten.quelle
Ich bearbeite die Ajax-Anfrage mit Selenium und dem Firefox-Webtreiber. Es ist nicht so schnell, wenn Sie den Crawler als Daemon benötigen, aber viel besser als jede manuelle Lösung. Ich schrieb ein kurzes Tutorial hier als Referenz
quelle