Die Autorin des Artikels, dessen Übersetzung wir heute veröffentlichen, sagt, dass ihr Ziel darin besteht, über die Entwicklung eines Web-Scraper in Python mit Selenium zu sprechen, der nach Flugpreisen sucht. Bei der Suche nach Tickets werden flexible Daten verwendet (+ - 3 Tage relativ zu den angegebenen Daten). Scraper speichert die Suchergebnisse in einer Excel-Datei und sendet an die Person, die sie gestartet hat, eine E-Mail mit allgemeinen Informationen darüber, was er gefunden hat. Das Ziel dieses Projekts ist es, Reisenden zu helfen, die besten Angebote zu finden.

Wenn Sie beim Umgang mit dem Material das Gefühl haben, verloren zu sein, lesen Sie
diesen Artikel.
Was suchen wir?
Sie können das hier beschriebene System nach Ihren Wünschen verwenden. Zum Beispiel habe ich damit nach Wochenendtouren und Tickets für meine Heimatstadt gesucht. Wenn Sie es ernst meinen, profitable Tickets zu finden, können Sie das Skript auf dem Server ausführen (ein einfacher
Server für 130 Rubel pro Monat ist dafür gut geeignet) und es ein- oder zweimal am Tag ausführen lassen. Die Suchergebnisse werden per E-Mail an Sie gesendet. Außerdem empfehle ich, dass Sie alles so konfigurieren, dass das Skript die Excel-Datei mit den Suchergebnissen im Dropbox-Ordner speichert, sodass Sie solche Dateien von überall und jederzeit anzeigen können.
Ich habe noch keine fehlerhaften Tarife gefunden, aber ich glaube, dass dies möglich istBei der Suche wird, wie bereits gesagt, ein „flexibles Datum“ verwendet, das Skript findet Angebote, die innerhalb von drei Tagen ab dem angegebenen Datum liegen. Obwohl beim Starten des Skripts nur in einer Richtung nach Angeboten gesucht wird, kann es leicht verfeinert werden, sodass Daten in mehreren Flugrichtungen erfasst werden können. Mit seiner Hilfe können Sie sogar nach fehlerhaften Tarifen suchen, solche Funde können sehr interessant sein.
Warum brauche ich einen anderen Web Scraper?
Als ich anfing, Web Scraping zu machen, war es ehrlich gesagt nicht besonders interessant. Ich wollte mehr Projekte im Bereich der prädiktiven Modellierung, der Finanzanalyse und möglicherweise im Bereich der Analyse der emotionalen Färbung von Texten durchführen. Es stellte sich jedoch heraus, dass es sehr interessant war, herauszufinden, wie ein Programm erstellt werden kann, das Daten von Websites sammelt. Als ich mich mit diesem Thema befasste, wurde mir klar, dass Web Scraping die „Engine“ des Internets ist.
Sie können entscheiden, dass dies eine zu kühne Aussage ist. Aber denken Sie daran, wie Google mit einem Web-Scraper begann, den Larry Page mit Java und Python erstellt hat. Googlebots haben das Internet recherchiert und erkundet, um ihren Nutzern die bestmöglichen Antworten auf ihre Fragen zu bieten. Web Scraping hat unendlich viele Anwendungen, und selbst wenn Sie im Bereich Data Science an etwas anderem interessiert sind, benötigen Sie einige Scraping-Kenntnisse, um Daten für die Analyse zu erhalten.
Einige der hier verwendeten Tricks habe ich in einem wunderbaren
Buch über Web Scraping gefunden, das ich kürzlich erworben habe. Darin finden Sie viele einfache Beispiele und Ideen zur praktischen Anwendung des Studierten. Darüber hinaus gibt es ein sehr interessantes Kapitel zum reCaptcha-Test-Bypass. Für mich war dies eine Neuigkeit, da ich nicht wusste, dass es spezielle Tools und sogar ganze Services zur Lösung solcher Probleme gibt.
Reisen Sie gerne ?!
Auf die einfache und ziemlich harmlose Frage in der Überschrift dieses Abschnitts kann man oft eine positive Antwort hören, die ein paar Reisegeschichten der Person enthält, zu der er gefragt wurde. Die meisten von uns werden zustimmen, dass Reisen eine großartige Möglichkeit ist, in neue kulturelle Umgebungen einzutauchen und unseren Horizont zu erweitern. Wenn Sie jedoch jemandem eine Frage stellen, ob er gerne nach Flugtickets sucht, bin ich sicher, dass die Antwort darauf alles andere als positiv sein wird. Tatsächlich kommt hier Python zur Rettung.
Die erste Aufgabe, die wir auf dem Weg zur Schaffung eines Systems zur Suche nach Informationen über Flugtickets lösen müssen, ist die Auswahl einer geeigneten Plattform, mit der wir Informationen aufnehmen. Die Lösung für dieses Problem war für mich nicht einfach, aber am Ende entschied ich mich für den Kajak-Service. Ich habe die Dienste von Momondo, Skyscanner, Expedia und anderen ausprobiert, aber die Schutzmechanismen gegen Roboter auf diesen Ressourcen waren undurchdringlich. Nach mehreren Versuchen, bei denen ich mich mit Ampeln, Fußgängerüberwegen und Fahrrädern auseinandersetzen musste, um die Systeme davon zu überzeugen, dass ich ein Mensch bin, entschied ich, dass Kajak am besten zu mir passt, auch wenn dies hier der Fall ist Laden Sie in kurzer Zeit zu viele Seiten, und die Überprüfungen beginnen ebenfalls. Ich habe es geschafft, dass der Bot in Abständen von 4 bis 6 Stunden Anfragen an die Site sendet, und alles hat gut funktioniert. Bei der Arbeit mit Kayak treten auch regelmäßig Schwierigkeiten auf. Wenn Sie jedoch anfangen, sich mit Schecks zu beschäftigen, müssen Sie entweder manuell damit umgehen, dann den Bot starten oder einige Stunden warten, und die Schecks sollten aufhören. Bei Bedarf können Sie den Code gut für eine andere Plattform anpassen. Wenn Sie dies tun, können Sie ihn in den Kommentaren melden.
Wenn Sie gerade erst mit dem Web-Scraping beginnen und nicht wissen, warum einige Websites damit zu kämpfen haben, tun Sie sich selbst einen Gefallen und suchen Sie bei Google nach Wörtern, bevor Sie Ihr erstes Projekt in diesem Bereich starten "Web Scraping Etikette". Ihre Experimente können früher enden als Sie denken, wenn Sie sich unangemessen mit Web Scraping beschäftigen.
Erste Schritte
Hier ist eine allgemeine Übersicht darüber, was im Code unseres Web Scraper passieren wird:
- Importieren Sie die erforderlichen Bibliotheken.
- Öffnen Sie die Registerkarte Google Chrome.
- Aufruf der Funktion, die den Bot startet, Übergabe der Stadt und des Datums, die bei der Suche nach Tickets verwendet werden.
- Diese Funktion empfängt die ersten Suchergebnisse, sortiert nach den Kriterien der attraktivsten (besten), und drückt die Taste, um zusätzliche Ergebnisse zu laden.
- Eine andere Funktion sammelt Daten von der gesamten Seite und gibt einen Datenrahmen zurück.
- Die beiden vorherigen Schritte werden unter Verwendung von Sortiertypen nach Ticketpreis (günstig) und Fluggeschwindigkeit (am schnellsten) ausgeführt.
- An den Skriptbenutzer wird eine E-Mail mit einer kurzen Zusammenfassung der Ticketpreise (günstigste Tickets und Durchschnittspreis) gesendet, und ein Datenrahmen mit Informationen, die nach den drei oben genannten Indikatoren sortiert sind, wird als Excel-Datei gespeichert.
- Alle oben genannten Aktionen werden in einem Zyklus nach einem bestimmten Zeitraum ausgeführt.
Es ist zu beachten, dass jedes Selenium-Projekt mit einem Webtreiber beginnt. Ich benutze
Chromedriver , arbeite mit Google Chrome, aber es gibt andere Möglichkeiten. Beliebt sind auch PhantomJS und Firefox. Nachdem Sie den Treiber geladen haben, müssen Sie ihn in den entsprechenden Ordner legen. Damit ist die Vorbereitung für die Verwendung abgeschlossen. In den ersten Zeilen unseres Skripts wird ein neuer Chrome-Tab geöffnet.
Denken Sie daran, dass ich in meiner Geschichte nicht versuche, neue Horizonte zu eröffnen, um profitable Angebote für Flugtickets zu finden. Es gibt viel fortgeschrittenere Techniken, um solche Angebote zu finden. Ich möchte den Lesern dieses Materials nur eine einfache, aber praktische Möglichkeit bieten, dieses Problem zu lösen.
Hier ist der Code, über den wir oben gesprochen haben.
from time import sleep, strftime from random import randint import pandas as pd from selenium import webdriver from selenium.webdriver.common.keys import Keys import smtplib from email.mime.multipart import MIMEMultipart
Am Anfang des Codes sehen Sie die Paketimportbefehle, die in unserem Projekt verwendet werden.
randint
wird also verwendet, damit der Bot für eine zufällige Anzahl von Sekunden "einschlafen" kann, bevor ein neuer
randint
wird. Normalerweise kann kein einziger Bot darauf verzichten. Wenn Sie den obigen Code ausführen, wird ein Chrome-Fenster geöffnet, in dem der Bot mit Websites arbeitet.
Lassen Sie uns ein kleines Experiment durchführen und die Website kayak.com in einem separaten Fenster öffnen. Wählen Sie die Stadt, von der aus wir fliegen, die Stadt, in die wir fliegen möchten, sowie die Flugdaten. Bei der Auswahl der Daten überprüfen wir, ob der Bereich + -3 Tage beträgt. Ich habe den Code unter Berücksichtigung dessen geschrieben, was die Site als Antwort auf solche Anfragen produziert. Wenn Sie beispielsweise nur für bestimmte Daten nach Tickets suchen müssen, müssen Sie höchstwahrscheinlich den Bot-Code ändern. Wenn ich über den Code spreche, gebe ich entsprechende Erklärungen ab, aber wenn Sie sich verwirrt fühlen, lassen Sie es mich wissen.
Klicken Sie nun auf die Schaltfläche Start der Suche und sehen Sie sich den Link in der Adressleiste an. Es sollte wie der Link aussehen, den ich im folgenden Beispiel verwende, in dem die
kayak
, in der die URL gespeichert ist, deklariert und die
get
Methode des Webtreibers verwendet wird. Nach dem Klicken auf die Suchschaltfläche sollten die Ergebnisse auf der Seite angezeigt werden.
Als ich den Befehl
get
in wenigen Minuten mehr als zwei- bis dreimal verwendet habe, wurde ich gebeten, einen Test mit reCaptcha zu bestehen. Sie können diese Prüfung manuell durchführen und die Experimente fortsetzen, bis das System beschließt, eine neue Prüfung durchzuführen. Als ich das Skript getestet habe, hatte ich das Gefühl, dass die erste Suchsitzung immer ohne Probleme verläuft. Wenn Sie also mit dem Code experimentieren möchten, müssen Sie ihn nur regelmäßig manuell überprüfen und den Code in langen Intervallen zwischen den Suchsitzungen ausführen lassen. Ja, und wenn Sie darüber nachdenken, ist es unwahrscheinlich, dass eine Person Informationen zu Ticketpreisen benötigt, die zwischen den Suchvorgängen in 10-Minuten-Intervallen eingehen.
Arbeiten mit einer Seite mit XPath
Also haben wir das Fenster geöffnet und die Seite geladen. Um Preise und andere Informationen zu erhalten, müssen wir die XPath-Technologie oder CSS-Selektoren verwenden. Ich habe mich für XPath entschieden und hatte nicht das Bedürfnis, CSS-Selektoren zu verwenden, aber es ist durchaus möglich, so zu arbeiten. Das Bewegen einer Seite mit XPath kann eine entmutigende Aufgabe sein, und selbst wenn Sie die in
diesem Artikel beschriebenen Methoden verwenden, bei denen die entsprechenden Bezeichner aus dem Seitencode kopiert wurden, wurde mir klar, dass dies tatsächlich nicht der beste Weg ist, darauf zuzugreifen notwendige Elemente. Übrigens finden Sie in
diesem Buch eine hervorragende Beschreibung der Grundlagen der Arbeit mit Seiten mit XPath- und CSS-Selektoren. So sieht die entsprechende Webtreibermethode aus.
Also arbeiten wir weiter am Bot. Nutzen Sie das Programm, um die günstigsten Tickets auszuwählen. In der folgenden Abbildung ist der XPath-Auswahlcode rot hervorgehoben. Um den Code anzuzeigen, müssen Sie mit der rechten Maustaste auf das Element der Seite klicken, an der Sie interessiert sind, und im angezeigten Menü den Befehl Inspizieren auswählen. Dieser Befehl kann für verschiedene Seitenelemente aufgerufen werden, deren Code im Code-Anzeigefenster angezeigt und hervorgehoben wird.
Seitencode anzeigenBeachten Sie die folgenden Funktionen, um eine Bestätigung meiner Überlegungen zu den Nachteilen des Kopierens von Selektoren aus Code zu erhalten.
Folgendes erhalten Sie beim Kopieren von Code:
//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/span
Um etwas Ähnliches zu kopieren, müssen Sie mit der rechten Maustaste auf den Teil des Codes klicken, der Sie interessiert, und im angezeigten Menü Kopieren> XPath kopieren auswählen.
Folgendes habe ich verwendet, um die Schaltfläche "Günstigstes" zu definieren:
cheap_results = '//a[@data-code = "price"]'
Kopieren> XPath-Befehl kopierenEs ist ziemlich offensichtlich, dass die zweite Option viel einfacher aussieht. Bei der Verwendung wird nach dem Element a gesucht, dessen
data-code
Attribut dem
price
. Mit der ersten Option wird nach einem
id
Element gesucht, das
wtKI-price_aTab
, und der XPath-Pfad zum Element sieht wie folgt aus:
/div[1]/div/div/div[1]/div/span/span
. Eine ähnliche XPath-Anforderung an eine Seite reicht aus, jedoch nur einmal. Ich kann jetzt sagen, dass sich die
id
beim nächsten Laden der Seite ändert. Die
wtKI
Zeichenfolge ändert sich bei jedem Laden der Seite dynamisch. Daher ist der Code, in dem sie verwendet wird, nach dem nächsten erneuten Laden der Seite unbrauchbar. Nehmen Sie sich also etwas Zeit, um XPath herauszufinden. Dieses Wissen wird Ihnen gut dienen.
Es sollte jedoch beachtet werden, dass das Kopieren von XPath-Selektoren nützlich sein kann, wenn Sie mit relativ einfachen Websites arbeiten, und wenn dies zu Ihnen passt, ist daran nichts auszusetzen.
Lassen Sie uns nun überlegen, was zu tun ist, wenn Sie alle Suchergebnisse in mehreren Zeilen innerhalb der Liste abrufen möchten. Sehr einfach. Jedes Ergebnis befindet sich in einem Objekt mit der
resultWrapper
Klasse. Das Herunterladen aller Ergebnisse kann in einer Schleife erfolgen, die der unten gezeigten ähnelt.
Es sollte beachtet werden, dass Sie, wenn Sie das oben Genannte verstehen, den größten Teil des Codes, den wir analysieren werden, leicht verstehen sollten. Im Verlauf der Arbeit dieses Codes wenden wir uns dem zu, was wir brauchen (tatsächlich ist dies das Element, in das das Ergebnis eingeschlossen ist), indem wir einen Mechanismus verwenden, um den Pfad anzugeben (XPath). Dies geschieht, um den Text des Elements
flight_containers
und in ein Objekt zu platzieren, aus dem Daten gelesen werden können (verwenden Sie zuerst
flight_containers
, dann
flights_list
).
Die ersten drei Zeilen werden angezeigt und wir können alles klar sehen, was wir brauchen. Wir haben jedoch interessantere Möglichkeiten, Informationen zu erhalten. Wir müssen Daten von jedem Element separat nehmen.
Zu arbeiten!
Es ist am einfachsten, eine Funktion zu schreiben, um zusätzliche Ergebnisse zu laden. Beginnen wir also damit. Ich möchte die Anzahl der Flüge maximieren, über die das Programm Informationen erhält, und gleichzeitig keine Verdächtigungen im Dienst hervorrufen, die zur Überprüfung führen. Daher klicke ich jedes Mal, wenn die Seite angezeigt wird, auf die Schaltfläche Weitere Ergebnisse laden. In diesem Code sollten Sie auf den
try
Block achten, den ich hinzugefügt habe, da die Schaltfläche manchmal nicht normal geladen wird. Wenn Sie auch darauf stoßen, kommentieren Sie die Aufrufe dieser Funktion im Code der Funktion
start_kayak
aus, den wir weiter unten diskutieren werden.
Nach einer langen Analyse dieser Funktion (manchmal kann ich mich mitreißen lassen) sind wir nun bereit, eine Funktion zu deklarieren, die sich mit dem Scraping von Seiten befasst.
Ich habe bereits das meiste gesammelt, was in der nächsten Funktion namens
page_scrape
. Manchmal stellen sich die zurückgegebenen Daten über die Stufen des Pfades als kombiniert heraus, für ihre Trennung verwende ich eine einfache Methode. Zum Beispiel verwende ich zum ersten Mal die Variablen
section_a_list
und
section_b_list
. Unsere Funktion gibt den
flights_df
. Auf diese Weise können wir die mit verschiedenen
flights_df
erhaltenen Ergebnisse trennen und später kombinieren.
def page_scrape(): """This function takes care of the scraping part""" xp_sections = '//*[@class="section duration"]' sections = driver.find_elements_by_xpath(xp_sections) sections_list = [value.text for value in sections] section_a_list = sections_list[::2]
Ich habe versucht, die Variablen so zu benennen, dass der Code klar ist. Denken Sie daran, dass Variablen, die mit
a
sich auf den ersten Schritt des Pfads und
b
auf den zweiten beziehen. Fahren Sie mit der nächsten Funktion fort.
Hilfsmechanismen
Jetzt haben wir eine Funktion, mit der Sie zusätzliche Suchergebnisse laden können, und eine Funktion, um diese Ergebnisse zu verarbeiten. Dieser Artikel könnte hierzu vervollständigt werden, da diese beiden Funktionen alles Notwendige zum Scraping von Seiten bieten, die unabhängig geöffnet werden können. Einige der oben diskutierten Hilfsmechanismen haben wir jedoch noch nicht berücksichtigt. Dies ist beispielsweise ein Code zum Senden von E-Mails und anderen Dingen. All dies finden Sie in der Funktion
start_kayak
, die wir jetzt betrachten.
Um diese Funktion nutzen zu können, benötigen Sie Informationen zu Städten und Daten. Mithilfe dieser Informationen bildet sie einen Link in der
kayak
, über den zu der Seite gewechselt wird, auf der die Suchergebnisse nach ihrer besten Übereinstimmung mit der Abfrage sortiert werden. Nach der ersten Scraping-Sitzung arbeiten wir mit den Preisen in der Tabelle oben auf der Seite. Wir finden nämlich den minimalen Ticketpreis und den Durchschnittspreis. All dies wird zusammen mit der von der Website ausgegebenen Vorhersage per E-Mail gesendet. Auf der Seite sollte sich die entsprechende Tabelle in der oberen linken Ecke befinden. Die Arbeit mit dieser Tabelle kann übrigens zu Fehlern bei der Suche nach genauen Daten führen, da in diesem Fall die Tabelle nicht auf der Seite angezeigt wird.
def start_kayak(city_from, city_to, date_start, date_end): """City codes - it's the IATA codes! Date format - YYYY-MM-DD""" kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to + '/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a') driver.get(kayak) sleep(randint(8,10))
Ich habe dieses Skript mit einem Outlook-Konto (hotmail.com) getestet. Ich habe nicht überprüft, ob das Google Mail-Konto ordnungsgemäß funktioniert. Dieses Mail-System ist sehr beliebt, aber es gibt viele mögliche Optionen. Wenn Sie ein Hotmail-Konto verwenden, müssen Sie nur Ihre Daten in den Code eingeben, damit alles funktioniert.
Wenn Sie verstehen möchten, was genau in separaten Abschnitten des Codes dieser Funktion ausgeführt wird, können Sie sie kopieren und mit ihnen experimentieren. Codeexperimente sind der einzige Weg, dies zu verstehen.
Bereites System
Nachdem alles, worüber wir gesprochen haben, erledigt ist, können wir eine einfache Schleife erstellen, in der unsere Funktionen aufgerufen werden. Das Skript fragt den Benutzer nach Daten zu Städten und Daten. Wenn Sie mit einem konstanten Neustart des Skripts testen, ist es unwahrscheinlich, dass Sie diese Daten jedes Mal manuell eingeben möchten. Daher können die entsprechenden Zeilen für den Testzeitpunkt auskommentiert werden, indem Sie diejenigen auskommentieren, die darunter liegen und in denen die für das Skript erforderlichen Daten fest festgelegt sind.
city_from = input('From which city? ') city_to = input('Where to? ') date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ') date_end = input('Return when? Please use YYYY-MM-DD format only ')
Hier ist der Testlauf des Skripts.
TestlaufskriptZusammenfassung
Wenn Sie an diesen Punkt kommen - herzlichen Glückwunsch! Jetzt haben Sie einen funktionierenden Web-Scraper, obwohl ich bereits viele Möglichkeiten sehe, ihn zu verbessern. Beispielsweise kann es in Twilio integriert werden, sodass anstelle von E-Mails Textnachrichten gesendet werden. Sie können ein VPN oder etwas anderes verwenden, um gleichzeitig Ergebnisse von mehreren Servern zu erhalten. Es gibt auch ein wiederkehrendes Problem beim Überprüfen des Site-Benutzers, ob er eine Person ist, aber dieses Problem kann auch gelöst werden. In jedem Fall haben Sie jetzt eine Basis, die Sie erweitern können, wenn Sie möchten. Stellen Sie beispielsweise sicher, dass die Excel-Datei als Anhang an eine E-Mail an den Benutzer gesendet wird.
