Scrapy ist ein Open-Source-Python-Framework, das für Web-Scraping in großem Maßstab entwickelt wurde. Es gibt uns alle Werkzeuge an die Hand, die wir brauchen, um Daten von jeder beliebigen Website zu extrahieren, zu verarbeiten und zu speichern.
Das Schöne an diesem Framework ist, wie einfach es ist, benutzerdefinierte Spider in großem Umfang zu erstellen und bestimmte Elemente mit CSS- oder XPath-Selektoren zu sammeln, Dateien (JSON, CSV usw.) zu verwalten und unsere Projekte zu pflegen. Wenn Sie schon immer einen Web Scraper bauen wollten, sich aber gefragt haben, wie Sie mit Scrapy anfangen sollen, sind Sie hier genau richtig.
In diesem Scrapy-Tutorial lernen Sie, wie man:
- Installieren Sie Scrapy auf Ihrem Rechner
- Ein neues Projekt erstellen
- Scrapy Shell zum Testen von Selektoren verwenden
- Bauen Sie eine benutzerdefinierte Spinne
- Extrahieren bestimmter Datenbits
- Importieren Sie Ihre ausgewerteten Daten in eine JSON- oder CSV-Datei
Obwohl es gut wäre, einige Vorkenntnisse über die Funktionsweise von Python zu haben, richten wir uns mit diesem Tutorial an absolute Anfänger. Sie können also sicher sein, dass Sie jedem Schritt folgen können.
Anmerkung: Wenn Sie diesen Artikel nicht ohne Kenntnisse der Python-Syntax durcharbeiten möchten, empfehlen wir Ihnen das Python-Tutorial von W3School als Ausgangspunkt.
Inhaltsübersicht
1. Wie Sie Scrapy auf Ihrem Rechner installieren
Das Scrapy-Team empfiehlt, das Framework in einer virtuellen Umgebung (VE) statt systemweit zu installieren, und genau das werden wir auch tun.
Öffnen Sie die Eingabeaufforderung auf Ihrem Desktop (oder dem Verzeichnis, in dem Sie Ihre virtuelle Umgebung erstellen möchten) und geben Sie ein python -m venv scrapy_tutorial
.
Die venv
wird eine VE unter dem von Ihnen angegebenen Pfad erstellt - in diesem Fall, scrapy_Anleitung - und installieren Sie die neueste Version von Python, die Sie in Ihrem System haben.
Außerdem fügt es einige Verzeichnisse mit einer Kopie des Python-Interpreters, der Standardbibliothek und verschiedenen unterstützenden Dateien hinzu.
Wenn Sie überprüfen möchten, ob sie erstellt wurde, geben Sie dir
in Ihrer Eingabeaufforderung und es werden alle Verzeichnisse aufgelistet, die Sie haben.
Um Ihre neue Umgebung zu aktivieren, geben Sie ein scrapy_tutorial\scripts\activate.bat
und führen Sie es aus.
Jetzt, wo wir uns in unserer Umgebung befinden, verwenden wir pip3 install scrapy
um das Framework herunterzuladen und es in unserer virtuellen Umgebung zu installieren.
Und das war's. Wir sind jetzt bereit, unser Projekt zu starten.
2. Erstellen Sie ein Scrapy-Projekt
Gehen Sie in Ihrer Eingabeaufforderung zu cd scrapy_tutorial
und tippen Sie dann scrapy startproject scrapytutorial
:
Mit diesem Befehl werden alle Projektdateien automatisch in einem neuen Verzeichnis angelegt:
- scrapytutorial (Ordner)
- Scrapy.cfg
- scrapytutorial/
- Spinnen (Ordner)
- _init_
- Artikel
- Middlewares
- Pipelines
- Einstellung
3. Scrapy Shell zum Testen von Selektoren verwenden
Bevor wir uns daran machen, einen Spider zu schreiben, müssen wir uns zunächst die Website ansehen, die wir scrapen wollen, und herausfinden, an welchem Element wir uns festhalten können, um die gewünschten Daten zu extrahieren.
Scrapy Shell laden
Für dieses Projekt werden wir crawlen https://www.wine-selection.com/
Shop, um den Produktnamen, den Link und den Verkaufspreis zu erfassen.
Um den Test zu beginnen, lassen Sie uns Folgendes ausführen scrapy shell
und lassen Sie es laden.
Damit können wir die HTML-Seite, die wir scrapen wollen, herunterladen und sie abfragen, um herauszufinden, welche Befehle wir beim Schreiben unseres Scraper-Skripts verwenden wollen.
Nachdem die Shell fertig geladen ist, verwenden wir den Befehl fetch und geben die URL ein, die wir herunterladen möchten: fetch('https://www.wine-selection.com/shop')
und drücken Sie die Eingabetaste.
Sie sollte einen 200-Status zurückgeben, was bedeutet, dass die Website funktioniert, und speichern Sie sie in der response
variabel.
Hinweis: Wir können dies überprüfen, indem wir Folgendes eingeben response
auf unserer Kommandozeile.
Überprüfen der Seite
Perfekt. Unsere Seite ist jetzt bereit für die Inspektion.
Wir können tippen view(response)
und es wird die heruntergeladene Seite in unserem Standardbrowser geöffnet oder Sie öffnen einfach unseren Browser und navigieren zu unserer Zielseite. Beides ist in Ordnung.
Mit dem Inspektionstool in Chrome (Strg + Umschalt + c) identifizieren wir die Klassen oder IDs, mit denen wir jedes Element auf der Seite auswählen können.
Bei näherer Betrachtung sind alle Informationen, die wir abrufen wollen, in <div>
mit class="txt-wrap”
über alle Produktkarten hinweg.
Lassen Sie uns diese Klasse als Selektor verwenden, indem wir Folgendes eingeben response.css('div.txt-wrap')
und es werden alle Elemente zurückgegeben, die dieser Klasse entsprechen - was, um ehrlich zu sein, wirklich überwältigend ist und keine große Hilfe sein wird.
Um das Ganze noch ein bisschen weiter zu treiben, geben wir diesen Befehl noch einmal ein, fügen aber die .get( )
Befehl am Ende der Zeichenkette.
Es hat den gesamten HTML-Code in diesem ersten div zurückgegeben, der die Kriterien erfüllt, und wir können den Preis, den Namen und den Link in diesem Code sehen.
CSS-Selektoren in Scrapy verwenden
Um unseren Prozess effizienter zu gestalten, werden wir diese letzte Antwort als Variable speichern. Geben Sie einfach ein wines = response.css('div.txt-wrap')
und jetzt können wir diese Variable in der nächsten Zeile aufrufen.
Da wir den Namen des Produkts abrufen möchten, müssen wir prüfen, wo der Name noch einmal ausgegeben wird.
Es scheint, dass der Titel des Produkts in einem Link-Tag ohne Klasse enthalten ist. Was können wir also jetzt tun?
Die gute Nachricht ist, dass es nur einen Link innerhalb unserer div
, also können wir einfach hinzufügen wines.css('a::text').get()
um unserem Programm mitzuteilen, dass es den Text, der sich in der <a></a>
Tags.
Anmerkung: wenn wir CSS-Selektoren verwenden, können wir ::text
nach unserem Selektor und es wird nur der Text innerhalb des Elements zurückgegeben. Für XPath, fügen Sie /text()
- z.B.. wines-xpath('//*[@id="content"]/div[1]/div/div[2]/h2/a/text()').get()
.
Jetzt können wir den gleichen Prozess für die restlichen Elemente durchführen:
- Den Preis erhalten:
wines.css('strong.price::text').get()
- Sie erhalten den Produktlink:
wines.css('a').attrib['href']
Tipp: möchten Sie vielleicht das Leerzeichen und das Dollarzeichen ($) nicht in Ihren Daten haben. Um dies schnell zu eliminieren, fügen Sie .replace('$ ', '')
.
4. Erstellen Sie eine benutzerdefinierte Spinne
Öffnen Sie zunächst den Projektordner in VScode (oder Ihrem bevorzugten Code-Editor) und erstellen Sie eine neue Datei im Ordner Spinne Ordner namens winespider.py
.
Schreiben Sie in die Datei den folgenden Code:
</p>
importieren scrapy
class WinesSpider(scrapy.Spider):
name = "winy"
start_urls = ['https://www.wine-selection.com/shop']
def parse(self, response):
for wines in response.css('div.txt-wrap'):
yield {
'name': wines.css('a::text').get(),
'preis': wines.css('strong.preis::text').get().replace('$ ',''),
'link': wines.css('a').attrib['href'],
}
<p>
Lassen Sie uns diesen Code aufschlüsseln:
- Wir haben Scrapy in unser Projekt importiert, und zwar ganz oben in der Datei.
- Wir haben eine neue Klasse (spider) definiert und die Unterklasse Spider hinzugefügt.
- Wir haben ihr dann einen eindeutigen Namen gegeben (winy), die nicht mit einer anderen Spinne innerhalb des Projekts identisch sein kann.
- Um unserem Spider eine Zielseite zu geben, haben wir
start_urls = ['https://www.wine-selection.com/shop']
. Wir hätten auch eine durch Kommas getrennte Liste von URLs hinzufügen können, aber wir werden unseren Spider später durch die Paginierung der Website laufen lassen. Wir haben also nur die erste Seite angegeben. - Zuletzt haben wir Scrapy mitgeteilt, welche Informationen es in der HTML-Datei finden soll. Wie Sie feststellen konnten, haben wir dieselbe Logik verwendet, die wir zuvor in Scrapy Shell definiert haben, und haben die
parse()
Funktion, um die Download-Seite zu bearbeiten.
5. Starten Sie Ihren Scraper und speichern Sie die Daten in einer JSON-Datei.
Um Ihren Scraper auszuführen, beenden Sie Scrapy Shell und wechseln Sie in den Projektordner Ihrer Eingabeaufforderung und geben Sie ein: scrapy crawl
und den Namen Ihrer Spinne:
Wenn alles funktioniert, werden die ausgewerteten Daten in Ihrer Befehlszeile protokolliert:
Jetzt, da wir wissen, dass es funktioniert, können wir es noch einmal ausführen, aber dieses Mal mit -o winy.json
um Scrapy anzuweisen, die ausgewerteten Daten in einer JSON-Datei namens winy.
Scrapy übernimmt dann alles für Sie, so dass Sie sich nicht um Ihre eigene Ausgabekonfiguration kümmern müssen.
6. Lassen Sie Ihren Scraper die Paginierung durchsuchen
Wenn Sie mitgemacht haben, dann herzlichen Glückwunsch, Sie haben gerade Ihren ersten Web Crawling Spider mit Scrapy geschrieben! Das ist beeindruckend.
Fügen wir unserem Spider weitere Funktionen hinzu, indem wir ihn die nächste Seite der Paginierung verfolgen lassen.
Diese Seite hat eine "nächste" - was eine gute Nachricht sein könnte. Nach eingehender Prüfung sieht es so aus, als ob der Ziellink, dem unser Spider folgen soll, zwischen Link-Tags innerhalb einer Liste eingebettet ist.
Bevor wir ihn zu unserer Hauptdatei hinzufügen, testen wir den Selektor mit Scrapy Shell, um unsere Logik zu überprüfen.
Wie oben erwähnt, müssen wir fetch()
die URL und verwenden dann die Antwort, um unsere Daten zu extrahieren, aber es gibt einen Haken: alle Links in der Paginierung verwenden die gleichen Klassen.
Wenn wir also versuchen zu schreiben:
</p>
next_page = response.css('span.page-link > a').attrib['ahref']
wenn next_page nicht None ist:
yield response.follow(nächste_Seite, callback=self.parse)
<p>
Er wird die erste Seite verwenden, die er unter dem angegebenen Pfad findet. Unser Scraper dreht sich also im Kreis.
Hier die gute Nachricht: Wenn wir uns die Struktur der Schaltfläche genau ansehen, gibt es eine rel = next
attribute
die nur diese Taste hat. Das muss unser Ziel sein!
Zeit, unseren Code ein letztes Mal zu aktualisieren...
</p>
importieren scrapy
class WinesSpider(scrapy.Spider):
name = "winy"
start_urls = ['https://www.wine-selection.com/shop']
def parse(self, response):
for wines in response.css('div.txt-wrap'):
yield {
'name': wines.css('a::text').get(),
'preis': wines.css('strong.preis::text').get().replace('$ ',''),
'link': wines.css('a').attrib['href'],
}
nächste_seite = response.css('a[rel=next]').attrib['href']
wenn next_page nicht None ist:
yield response.follow(nächste_Seite, callback=self.parse)
<p>
... und führen Sie es mit scrapy crawl winy -o winy.csv
um unser Feld in einem einfacher zu verwendenden Format zu speichern.
Wie Sie sehen können, werden jetzt 148 Produkte angezeigt.
Tipp: Wenn Sie einer bestehenden Datei weitere Informationen hinzufügen möchten, brauchen Sie nur Ihren Scraper zu starten und ein klein geschriebenes "-o" zu verwenden (z.B. scrapy crawl -o winy.csv
). Wenn Sie die gesamte Datei außer Kraft setzen möchten, verwenden Sie stattdessen ein großes "-O" (z.B. scrapy crawl -O winy.csv
).
ScraperAPI und Scrapy Integration
Gut gemacht! Sie haben gerade Ihren ersten Scrapy Web Scraper erstellt.
Natürlich gibt es keinen Scraper, der für alle gleich gut geeignet ist. Jede Website ist anders strukturiert, so dass Sie sich dort zurechtfinden müssen.
Dank Scrapy können Sie jedoch benutzerdefinierte Spider für jede Seite erstellen und diese pflegen, ohne den Rest zu beeinträchtigen. Mit Scrapy lassen sich Ihre Projekte leichter verwalten und skalieren.
Wenn Sie jedoch ein großes Projekt planen, werden Sie schnell feststellen, dass die Verwendung von Scrapy allein nicht ausreichend ist.
Für einige Seiten müssen Sie Ihren Spidern mitteilen, wie sie mit Verboten und CAPTCHAs umgehen, JavaScript ausführen und Geotargeting anwenden sollen.
Diese Herausforderungen bedeuten zusätzlichen Zeitaufwand für die Programmierung und können in manchen Fällen ein einfaches Projekt zu einem absoluten Alptraum machen.
Genau dafür wurde ScraperAPI entwickelt. Mit jahrelanger statistischer Analyse, maschinellem Lernen, riesigen Browser-Farmen und Proxys von Drittanbietern verhindert sie, dass Ihr Scraper von Anti-Scraping-Techniken blockiert wird.
Es gibt mehrere Möglichkeiten, ScraperAPI zu verwenden. Der einfachste Weg ist die Verwendung einer cURL, um Ihre Anfrage zu senden. Etwa so:
start_urls = ['http://api.scraperapi.com?api_key={yourApiKey}&url=https://www.wine-selection.com/shop']
Dadurch wird Ihre Anfrage über die ScraperAPI-Server gesendet, wo das Tool auswählt, welcher Header der geeignetere ist, die IP-Adresse zwischen den einzelnen Anfragen rotiert und CAPTCHAs automatisch verarbeitet.
Um Ihren API-Schlüssel zu erhalten, erstellen Sie einfach ein kostenloses ScraperAPI-Konto. Sie finden Ihren Schlüssel in Ihrem Dashboard und 5000 kostenlose API-Credits, um die volle Funktionalität des Tools zu testen.
Diese Methode eignet sich jedoch nicht für unseren Scraper, da wir ihn brauchen, um mehrere URLs zu scrapen, indem wir den Links folgen. Diese Logik wird nur für die erste Anfrage funktionieren, nicht aber für die restlichen Anfragen.
Der erste Schritt bei dieser Integration ist die Erstellung der URL.
Definieren Sie die get_scraperapi_url()
Methode
Um unsere neue URL zu erstellen, müssen wir die Nutzdaten und die Funktion urlencode verwenden.
Wir beginnen mit dem Hinzufügen einer neuen Abhängigkeit am Anfang unserer Datei und definieren darunter eine Konstante namens API_KEY:
</p>
importieren scrapy
from urllib.parse import urlencode
API_KEY = '51e43be283e4db2a5afb62660fcxxxxx'
<p>
Anmerkung: Denken Sie daran, Ihren API-Schlüssel zu verwenden, wenn Sie Ihren Scraper schreiben.
Jetzt sind wir bereit, unsere neue Methode zu definieren:
</p>
def get_scraperapi_url(url):
payload = {'api_key': API_KEY, 'url': url}
proxy_url="http://api.scraperapi.com/?" + urlencode(payload)
return proxy_url
<p>
Diese Methode teilt unserem Scraper mit, wie die URL für die Anfrage aufgebaut werden soll, indem unser API-Schlüssel und die Ziel-URL hinzugefügt werden.
Senden Sie eine Anfrage über ScraperAPI-Server
Wir haben die start_urls
Funktion, um unsere Anfrage zu senden. Diese speichert die zurückgegebenen Informationen automatisch in einer Antwortvariablen.
In diesem Fall müssen wir eine Methode definieren, die die vorherige Methode verwendet und beim Senden der Anfrage die zusätzlichen Strings zu unserer URL hinzufügt.
</p>
def start_requests(self):
urls = ['https://www.wine-selection.com/shop']
for url in urls:
yield scrapy.Request(url=get_scraperapi_url(url), callback=self.parse)
<p>
Wie wir sehen können, verwendet unser Scraper die Werte in get_scraperapi_url(url)
und die URLs innerhalb der urls-Variable, um die Anfrage zu senden. Nachdem unser Spider also den gesamten Code durchlaufen und eine neue URL gefunden hat, wird er in einer Schleife zurückgehen und die URL für jede neue Anfrage auf dieselbe Weise konstruieren.
Der Rest unseres Codes bleibt unverändert:
</p>
importieren scrapy
from urllib.parse import urlencode
API_KEY = '51e43be283e4db2a5afb62660xxxxxxx'
def get_scraperapi_url(url):
payload = {'api_key': API_KEY, 'url': url}
proxy_url="http://api.scraperapi.com/?" + urlencode(payload)
return proxy_url
class WinesSpider(scrapy.Spider):
name = "winy"
def start_requests(self):
urls = ['https://www.wine-selection.com/shop']
for url in urls:
yield scrapy.Request(url=get_scraperapi_url(url), callback=self.parse)
def parse(self, response):
for wines in response.css('div.txt-wrap'):
yield {
'name': wines.css('a::text').get(),
'preis': wines.css('strong.preis::text').get().replace('$ ',''),
'link': wines.css('a').attrib['href'],
}
nächste_seite = response.css('a[rel=next]').attrib['href']
wenn next_page nicht None ist:
yield response.follow(nächste_Seite, callback=self.parse)
<p>
Wenn wir unseren Scraper jetzt ausführen, erhalten wir die gleichen Ergebnisse wie zuvor, ohne jedoch zu riskieren, dass unser Rechner gesperrt oder auf eine schwarze Liste gesetzt wird.
Wie cool ist das denn?
Sie suchen nach einer Möglichkeit, LinkedIn mit Python zu scrapen? Wir haben eine einfache Anleitung, der Sie folgen können.