HTML ist fast intuitiv. CSS ist ein großer Fortschritt, der die Struktur einer Seite sauber von ihrem Erscheinungsbild trennt. JavaScript fügt etwas pazazz hinzu. Das ist die Theorie. Die reale Welt ist etwas anders.
In diesem Lernprogramm erfahren Sie, wie der Inhalt, den Sie im Browser sehen, tatsächlich gerendert wird, und wie Sie ihn gegebenenfalls abkratzen können. Insbesondere lernen Sie, wie man Disqus-Kommentare zählt. Unsere Tools sind Python und tolle Pakete wie Requests, BeautifulSoup und Selenium.
Beim Web-Scraping wird automatisch der Inhalt von Webseiten abgerufen, die für die Interaktion mit menschlichen Benutzern bestimmt sind, sie werden analysiert und einige Informationen werden extrahiert (möglicherweise navigieren Sie mit Links zu anderen Seiten). Es ist manchmal notwendig, wenn es keine andere Möglichkeit gibt, die erforderlichen Informationen zu extrahieren. Idealerweise bietet die Anwendung eine dedizierte API für den programmgesteuerten Zugriff auf ihre Daten. Es gibt mehrere Gründe, warum Web Scraping Ihr letzter Ausweg sein sollte:
Lassen Sie uns verstehen, was uns erwartet, indem wir uns die Ausgabe einiger gängiger Webanwendungscodes ansehen. Im Artikel Einführung in Vagrant finden Sie einige Disqus-Kommentare am unteren Rand der Seite:
Um diese Kommentare zu kratzen, müssen wir sie zuerst auf der Seite finden.
Jeder Browser seit Anbeginn der Zeit (den 1990er Jahren) hat die Möglichkeit unterstützt, den HTML-Code der aktuellen Seite anzuzeigen. Hier ist ein Ausschnitt aus der Ansichtsquelle von Introduction to Vagrant, der mit einem großen Teil des reduzierten und ublifizierten JavaScript beginnt, das nicht mit dem Artikel selbst zusammenhängt. Hier ist ein klein Teil davon:
Hier ist ein tatsächlicher HTML-Code von der Seite:
Das sieht ziemlich chaotisch aus, aber es ist überraschend, dass Sie die Disqus-Kommentare nicht im Quellcode der Seite finden.
Es stellt sich heraus, dass die Seite ein Mashup ist und die Disqus-Kommentare als iframe (Inline Frame) -Element eingebettet werden. Sie können es herausfinden, indem Sie mit der rechten Maustaste auf den Kommentarbereich klicken, und Sie werden feststellen, dass dort Rahmeninformationen und -quellen vorhanden sind:
Das macht Sinn. Das Einbetten von Inhalten von Drittanbietern als Iframe ist einer der Hauptgründe für die Verwendung von Iframes. Lass uns das finden Tag dann in der Hauptseite Quelle. Wieder vereitelt! Es gibt kein
Tag in der Hauptseite der Quelle.
Der Grund für diese Auslassung ist das Seitenquelle anzeigen
Zeigt den Inhalt an, der vom Server abgerufen wurde. Das endgültige DOM (Document Object Model), das vom Browser gerendert wird, kann jedoch sehr unterschiedlich sein. JavaScript tritt ein und kann das DOM nach Belieben manipulieren. Der iframe kann nicht gefunden werden, da er nicht vorhanden war, als die Seite vom Server abgerufen wurde.
Statisches Scraping ignoriert JavaScript. Es ruft Webseiten ohne Hilfe eines Browsers vom Server ab. Sie erhalten genau das, was Sie unter "Seitenquell anzeigen" sehen, und dann schneiden Sie sie in Würfel. Wenn der gewünschte Inhalt verfügbar ist, müssen Sie nicht weiter fortfahren. Wenn der Inhalt jedoch den Disqus-Kommentaren ähnelt, benötigen Sie dynamisches Scraping.
Beim dynamischen Scraping wird ein tatsächlicher Browser (oder ein Headless-Browser) verwendet, und JavaScript kann seine Aufgabe erfüllen. Dann fragt es das DOM ab, um den gesuchten Inhalt zu extrahieren. Manchmal müssen Sie den Browser automatisieren, indem Sie einen Benutzer simulieren, um den gewünschten Inhalt zu erhalten.
Sehen wir uns an, wie das statische Scraping mit zwei großartigen Python-Paketen funktioniert: Anfragen zum Abrufen von Webseiten und BeautifulSoup zum Analysieren von HTML-Seiten.
Installieren Sie zuerst pipenv und dann: pipenv Installationsanfragen beautifulsoup4
Dadurch wird auch eine virtuelle Umgebung für Sie erstellt. Wenn Sie den Code von Gitlab verwenden, können Sie dies einfach tun pipenv installieren
.
Das Abrufen einer Seite mit Anforderungen ist ein Einzeiler: r = request.get (url)
Das Antwortobjekt hat viele Attribute. Die wichtigsten sind OK
und Inhalt
. Wenn die Anfrage dann fehlschlägt r.ok
wird falsch sein und Inhalt
wird den Fehler enthalten. Der Inhalt ist ein Bytestrom. Es ist in der Regel besser, es im Umgang mit Text in utf-8 zu decodieren:
>>> r = request.get ('http://www.c2.com/no-such-page') >>> r.ok False >>> drucken (r.content.decode ('utf-8') ))404 Nicht gefunden Nicht gefunden
Die angeforderte URL / ggg wurde auf diesem Server nicht gefunden.
Apache / 2.0.52 (CentOS) -Server unter www.c2.com Port 80
Wenn alles in Ordnung ist, dann Inhalt
enthält die angeforderte Webseite (wie Seitenquell).
Das get_page ()
Die folgende Funktion ruft eine Webseite nach URL ab, dekodiert sie in UTF-8 und analysiert sie mithilfe des HTML-Parsers in ein BeautifulSoup-Objekt.
def get_page (url): r = request.get (url) content = r.content.decode ('utf-8') gibt BeautifulSoup zurück (content, 'html.parser')
Sobald wir ein BeautifulSoup-Objekt haben, können wir Informationen von der Seite extrahieren. BeautifulSoup bietet viele Suchfunktionen, um Elemente auf der Seite zu finden und tief verschachtelte Elemente zu untersuchen.
Tuts + Author-Seiten enthalten mehrere Tutorials. Hier ist meine Autorenseite. Auf jeder Seite gibt es bis zu 12 Tutorials. Wenn Sie mehr als 12 Tutorials haben, können Sie zur nächsten Seite navigieren. Das HTML für jeden Artikel ist in einem Etikett. Die folgende Funktion findet alle Artikelelemente auf der Seite, führt einen Drilldown mit ihren Links durch und extrahiert das Attribut href, um die URL des Lernprogramms abzurufen:
def get_page_articles (page): elements = page.findAll ('article') articles = [e.a.attrs ['href'] für e in elements] gibt Artikel zurück
Mit dem folgenden Code werden alle Artikel von meiner Seite abgerufen und gedruckt (ohne das allgemeine Präfix):
page = get_page ('https://tutsplus.com/authors/gigi-sayfan') articles = get_page_articles (page) prefix = 'https://code.tutsplus.com/tutorials' für a in articles: print (a [ len (Präfix):]) Ausgabe: Building-games-with-python-3-and-pygame-part-5 - cms-30085 building-games-with-python-3-und-pygame-part-4- cms-30084 Gebäude-Spiele-mit-Python-3-und-Pygame-Teil-3 - cms-30083 Gebäude-Spiele-Mit-Python-3-und-Pygame-Teil-2 - cms-30082 Gebäude-Spiele -mit-python-3-und-pygame-part-1 - cms-30081 beherrschen die reaktions-lebenszyklus-methoden - cms-29849 testdatenintensiver code-with-go-part-5-- cms-29852 testdatenintensiver Code-mit-gehen-Teil-4-cms-29851 testdatenintensiver Code-mit-gehen-Teil-3-cms-29850 testdatenintensiver Code -with-go-part-2 - cms-29848 testdatenintensiver-code-with-go-part-1 - cms-29847 make-your-go-programme-blitzschnell-mit-profiling-- cms-29809
Statisches Scraping war gut genug, um die Liste der Artikel abzurufen. Wie wir jedoch bereits gesehen haben, werden die Disqus-Kommentare von JavaScript als iframe-Element eingebettet. Um die Kommentare zu sammeln, müssen wir den Browser automatisieren und interaktiv mit dem DOM interagieren. Eines der besten Werkzeuge für diesen Job ist Selenium.
Selenium ist in erster Linie auf das automatisierte Testen von Webanwendungen ausgerichtet, eignet sich jedoch hervorragend als universelles Browser-Automatisierungswerkzeug.
Geben Sie diesen Befehl ein, um Selenium zu installieren: pipenv installieren Selen
Selenium benötigt einen Webtreiber (den Browser, den es automatisiert). Beim Web-Scraping spielt es normalerweise keine Rolle, welchen Treiber Sie wählen. Ich bevorzuge den Chrome-Treiber. Befolgen Sie die Anweisungen in diesem Selenium-Handbuch.
In einigen Fällen ziehen Sie es vor, einen Headless-Browser zu verwenden, dh es wird keine Benutzeroberfläche angezeigt. Theoretisch ist PhantomJS nur ein weiterer Web-Treiber. In der Praxis berichteten die Leute jedoch über Inkompatibilitätsprobleme, bei denen Selenium ordnungsgemäß mit Chrome oder Firefox funktioniert und manchmal mit PhantomJS ausfällt. Ich ziehe es vor, diese Variable aus der Gleichung zu entfernen und einen Browser-Webtreiber zu verwenden.
Lassen Sie uns dynamisches Scraping durchführen und mit Selenium Disqus-Kommentare zu Tuts + -Tutorials zählen. Hier sind die notwendigen Importe.
von selenium import webdriver von selenium.webdriver.common.by importieren Durch von selenium.webdriver.support.expected_conditions import (Präsenz_des_Elementes) von selenium.webdriver.support.wait importieren Sie WebDriverWait
Das get_comment_count ()
Die Funktion akzeptiert einen Selenium-Treiber und eine URL. Es verwendet die erhalten()
Methode des Treibers zum Abrufen der URL. Das ist ähnlich request.get ()
, Der Unterschied besteht jedoch darin, dass das Treiberobjekt eine Live-Darstellung des DOMs verwaltet.
Dann erhält es den Titel des Lernprogramms und sucht den Disqus-iframe anhand seiner übergeordneten ID disqus_thread
und dann der iframe selbst:
def get_comment_count (driver, url): driver.get (url) class_name = 'content-banner_title' name = driver.find_element_by_class_name (class_name) .text e = driver.find_element_by_id ('disqus_thread') disqus_iframe = e.find_element_name. iframe_url = disqus_iframe.get_attribute ('src')
Im nächsten Schritt wird der Inhalt des Iframes selbst abgerufen. Beachten Sie, dass wir auf das warten Anzahl Kommentare
Element vorhanden sein, da die Kommentare dynamisch geladen werden und noch nicht notwendigerweise verfügbar sind.
driver.get (iframe_url) wait = WebDriverWait (Treiber, 5) commentCountPresent = Präsenz_des_Elementes ((von.CLASS_NAME, 'comment-count')) wait.until (commentCountPresent) comment_count_span = driver.find_element_by_class_name ('comment-count') int (comment_count_span.text.split () [0])
Der letzte Teil ist, den letzten Kommentar zurückzugeben, wenn er nicht von mir gemacht wurde. Die Idee besteht darin, Kommentare zu finden, auf die ich noch nicht geantwortet habe.
last_comment = if comment_count> 0: e = driver.find_elements_by_class_name ('author') [- 1] last_author = e.find_element_by_tag_name ('a') last_author = e.get_attribute ('data-username') if last_author! = ' the_gigi ': e = driver.find_elements_by_class_name (' post-meta ') meta = e [-1] .find_element_by_tag_name (' a ') last_comment = dict (Autor = letzter_author, title = meta.get_attribute (' title '), wenn = meta.text) Rückgabewert, comment_count, last_comment
Web-Scraping ist eine nützliche Vorgehensweise, wenn auf die benötigten Informationen über eine Webanwendung zugegriffen werden kann, die keine entsprechende API bereitstellt. Das Extrahieren von Daten aus modernen Webanwendungen erfordert einige nicht triviale Arbeit, aber ausgereifte und gut konzipierte Tools wie Requests, BeautifulSoup und Selenium machen es wert.
Zögern Sie nicht, zu sehen, was wir für den Verkauf und das Studium auf dem Envato-Markt zur Verfügung haben, und zögern Sie nicht, Fragen zu stellen und mit dem untenstehenden Feed wertvolles Feedback zu geben.