Eine Webseite zu crawlen bedeutet, Software zu schreiben, die eine Menge von URLs abläuft, jede abruft und strukturierte Felder aus dem HTML extrahiert. So verwandeln Sie Seiten, die für menschliche Augen gebaut wurden, in Daten, die Sie abfragen können: Preisfeeds zum Monitoring, Artikelarchive für die Recherche, Angebotsraster für die Marktanalyse oder ein Trainingskorpus für ein Modell. Die meisten dieser Daten sind öffentlich und liegen offen sichtbar, aber sie per Hand in größerem Umfang zu lesen ist hoffnungslos, daher greifen Sie zu einem Crawler.
Dieser Leitfaden zeigt Ihnen, wie Sie eine Webseite mit Scrapy, Pythons ausgereiftem Crawling-Framework, crawlen, während jede Anfrage über die Crawling API geleitet wird, sodass die Seite gerendert zurückkommt und die Anfrage über eine rotierende, vertrauenswürdige IP statt Ihrer Datacenter-Adresse läuft. Sie bauen einen kleinen, ausführbaren Scrapy-Spider, der eine Suchergebnisseite abruft, ein Feld aus jeder Auflistung parst und saubere Datensätze ausgibt. Die Anleitung beschränkt sich auf öffentliche Auflistungsdaten, und am Ende gibt es eine kurze Anmerkung zum verantwortungsvollen Crawlen, die es wert ist, gelesen zu werden, bevor Sie das auf jedes reale Volumen ansetzen.
Was Sie bauen werden
Ein Scrapy-Spider aus einer einzigen Datei, der eine Suchergebnisseite über die Crawling API abruft und einen strukturierten Datensatz pro Ergebnis liefert. Wir verwenden eine Amazon-Suche als laufendes Beispiel, dasselbe wie die ursprüngliche Version dieses Tutorials verwendete, und ziehen zwei Felder aus jeder Produktkarte:
- Title: der Produkttiteltext, der auf der Ergebniskarte angezeigt wird.
- URL: der Link von der Karte auf die eigene Detailseite des Produkts.
Zwei Felder halten das Beispiel lesbar, und das Muster lässt sich auf jeden Selektor erweitern, den Sie hinzufügen möchten. Dieselbe Spider-Form funktioniert für jede Seite, die Sie berechtigt sind zu crawlen: Tauschen Sie die Start-URL und die Selektoren aus, und die Abruf-und-Parse-Schleife bleibt gleich.
Warum eine einfache Anfrage blockiert wird
Richten Sie eine bare Scrapy-Anfrage auf eine belebte kommerzielle Seite und zwei Dinge neigen dazu, schief zu gehen. Erstens rendern viele Seiten ihre Inhalte im Browser: Das anfängliche HTML ist eine dünne Hülle, und die Auflistungen erscheinen erst, nachdem das JavaScript der Seite ausgeführt wurde. Ein roher Abruf gibt die Hülle zurück, also gibt es nichts zu parsen. Zweitens beobachten große Seiten automatisierten Traffic. Eine Datacenter-IP, die schnelle, sich wiederholende Anfragen macht, die nicht wie ein echter Browser aussehen, wird mit einem CAPTCHA konfrontiert oder direkt blockiert, oft bevor Sie ein einziges Produkt sehen.
Ein Crawler, der tatsächlich funktioniert, braucht also zwei Dinge in derselben Anfrage: einen Browser, der die Seite rendert, und eine IP, die die Seite als echten Besucher liest. Sie können das selbst mit einem Headless-Browser plus einem Pool von rotierenden Residential-Proxys aufbauen, aber diese Teile zusammenzusetzen und gesund zu halten ist der Großteil der Arbeit. Die Crawling API faltet beides in einen Aufruf. Sie übergeben ihr eine URL, sie ruft die Seite hinter einer vertrauenswürdigen Residential-IP ab (und rendert sie in einem echten Browser, wenn Sie das verlangen), und sie gibt fertiges HTML für Scrapy zum Parsen zurück. Ihr Spider spricht mit einem Endpunkt und berührt nie eine Proxy-Liste.
Statt die Zielseite direkt anzufragen, fordert Ihr Spider https://api.crawlbase.com/?token=YOUR_CRAWLBASE_TOKEN&url=... an. Die API ruft das Ziel in Ihrem Auftrag über ihren IP-Pool ab und streamt den Antwort-Body zurück an Scrapy. Aus Scrapys Sicht ist es nur eine gewöhnliche HTTP-Antwort, also funktionieren alle Selektoren und Pipelines, die Sie bereits kennen, weiterhin.
Voraussetzungen
Einige Dinge müssen vorhanden sein, bevor Sie Code schreiben. Keines davon nimmt lange.
Grundlegendes Python. Sie sollten in der Lage sein, ein Python-Skript zu schreiben und auszuführen und Pakete mit pip zu installieren. Wenn Sie neu beim Crawling sind, deckt die breitere Anleitung zum scrape a website with Python die Grundlagen ab, die dieses Tutorial voraussetzt.
Python 3.8 oder höher. Bestätigen Sie Ihre Version mit python --version. Wenn Sie es nicht haben, installieren Sie es von python.org oder über eine Distribution wie Anaconda.
Ein Crawlbase-Konto und Token. Melden Sie sich an, öffnen Sie Ihr Dashboard und kopieren Sie Ihr Token. Crawlbase gibt Ihnen zwei: ein normales Token für statisches HTML und ein JavaScript-Token für Seiten, die Rendering benötigen. Wir verwenden den Platzhalter YOUR_CRAWLBASE_TOKEN durchgehend. Behandeln Sie es wie ein Passwort: Es authentifiziert Ihre Anfragen, also halten Sie es aus der Versionskontrolle heraus.
Das Projekt einrichten
Erstellen Sie eine isolierte Umgebung, damit die Abhängigkeiten des Projekts nicht mit anderen kollidieren, und installieren Sie dann die zwei Bibliotheken, die der Spider benötigt.
python --version python -m venv crawler_env source crawler_env/bin/activate pip install scrapy crawlbase
Unter Windows aktivieren Sie die Umgebung mit crawler_env\Scripts\activate statt der source-Zeile. Zwei Abhängigkeiten erledigen die Arbeit. scrapy ist das Crawling-Framework: Es verwaltet die Anfrage-Warteschlange, den Downloader und die Parse-Schleife. crawlbase ist der offizielle Python-Client für die Crawling API, und seine CrawlingAPI-Klasse hat einen buildURL-Helfer, der jede Ziel-URL in eine korrekte API-Anfrage, mit Token und allem, einschließt, sodass Sie diesen Query-String nicht von Hand zusammensetzen müssen.
Scrapy führt einen einzelnen Spider direkt aus einer Datei mit scrapy runspider aus, sodass Sie für dieses Tutorial kein vollständiges Projekt-Gerüst benötigen. Erstellen Sie eine Datei, die den Spider enthält:
touch myspider.py
Schritt 1: Eine Seite über die Crawling API abrufen
Beginnen Sie mit einem Spider, der nichts tut, außer zu beweisen, dass das Routing funktioniert. Erben Sie von scrapy.Spider, geben Sie ihm einen name und setzen Sie start_urls. Der eine Kniff hier ist, dass die Start-URL nicht direkt das Ziel ist: Sie wickeln sie mit api.buildURL ein, damit Scrapy den Crawling-API-Endpunkt anfragt und die API das Ziel für Sie abruft.
import scrapy from crawlbase import CrawlingAPI # Replace YOUR_CRAWLBASE_TOKEN with the token from your dashboard api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) class AmazonSpider(scrapy.Spider): name = "amazonspider" # Target page to crawl, then route it through the Crawling API targets = ["https://www.amazon.com/s?k=cold+brew+coffee+maker"] start_urls = [api.buildURL(url, {}) for url in targets]
Der Spider hat noch keine parse-Methode, also wird er die Seite abrufen und stoppen. Das ist Absicht: Sie möchten bestätigen, dass die Anfrage das Ziel über die API erreicht und mit Status 200 zurückkommt, bevor Sie einen einzigen Selektor schreiben. Führen Sie es aus dem Projektverzeichnis aus:
scrapy runspider myspider.py
Im Log sollten Sie eine Crawled (200)-Zeile für ein GET gegen api.crawlbase.com sehen, mit Ihrer Ziel-URL im url-Query-Parameter. Diese 200 ist der ganze Punkt dieses Schritts: Die Anfrage lief über die Crawling API, die API rief die Amazon-Suchseite hinter einer vertrauenswürdigen IP ab, und das gerenderte HTML kam zu Scrapy zurück. Da noch kein Parser vorhanden ist, protokolliert Scrapy, dass der Standard-parse-Callback nicht definiert ist, und schließt den Spider. Die Infrastruktur funktioniert; jetzt können Sie Daten extrahieren.
Dieses Crawled (200) gegen ein schwieriges kommerzielle Ziel ist der Teil, an dem die meisten Crawler scheitern. Die Crawling API hat die URL, die Sie an buildURL übergeben haben, genommen, die Seite hinter einer rotierenden Residential-IP abgerufen, bei Bedarf in einem echten Browser gerendert und Scrapy fertiges HTML übergeben, sodass Sie keine eigene Headless-Browser-Flotte und keinen Proxy-Pool betreiben müssen. Richten Sie es zuerst auf Ihr eigenes Ziel in der kostenlosen Stufe.
Schritt 2: Felder mit CSS- und XPath-Selektoren parsen
Jetzt fügen Sie eine parse-Methode hinzu. Scrapy ruft sie automatisch mit der response für jede abgerufene Seite auf, und die Response stellt sowohl CSS- als auch XPath-Selektoren über das HTML bereit. Für jede Produktkarte auf der Suchseite ziehen Sie den Titel und den Link und yielden ein kleines Dictionary. Scrapy sammelt alles, was Sie yielden, als gescrapte Items.
def parse(self, response): for card in response.css("div[data-component-type='s-search-result']"): title = card.css("h2 a span::text").get() href = card.css("h2 a::attr(href)").get() if not title or not href: continue yield { "title": title.strip(), "url": response.urljoin(href), }
Einige Dinge sind erwähnenswert. Der Karten-Selektor zielt auf ein stabiles data-component-type-Attribut statt auf eine zerbrechliche Utility-Klasse, was die Art von dauerhaftem Anker ist, den Sie auf jeder Seite bevorzugen sollten. response.css(...).get() gibt den ersten Treffer als Text oder None zurück, wenn nichts passt, sodass die if not title or not href-Wächter gesponserte Plätze und Layout-Zeilen überspringt, die nicht beide Felder tragen. response.urljoin(href) verwandelt den relativen Link, den die Karte Ihnen gibt, in eine absolute URL. Wenn Sie XPath bevorzugen, lauten dieselben zwei Felder card.xpath(".//h2//a//span/text()").get() und card.xpath(".//h2/a/@href").get(). CSS und XPath sind hier austauschbar; wählen Sie, was für ein bestimmtes Feld lesbarer ist. Der tiefere Vergleich der beiden liegt im Leitfaden zu web scraping with XPath and CSS selectors.
Site-Markup ändert sich ohne Ankündigung, und die obigen Selektoren sind eine Startvorlage, kein Vertrag. Wenn title oder url für jede Karte None zurückgibt, öffnen Sie die Live-Seite in den Dev-Tools Ihres Browsers, untersuchen Sie erneut eine Produktkarte und aktualisieren Sie den Selektor. Periodische Selektorwartung ist bei jedem Produktions-Crawler normal, kein Zeichen dafür, dass etwas kaputt ist.
Schritt 3: Den vollständigen Spider zusammensetzen und ausführen
Fügen Sie die Teile in einer Datei zusammen. Dies ist der vollständige, ausführbare Spider: der Import, der API-Client, die über buildURL gerouteten Start-URLs und die parse-Methode.
import scrapy from crawlbase import CrawlingAPI # Replace YOUR_CRAWLBASE_TOKEN with the token from your dashboard api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) class AmazonSpider(scrapy.Spider): name = "amazonspider" targets = ["https://www.amazon.com/s?k=cold+brew+coffee+maker"] start_urls = [api.buildURL(url, {}) for url in targets] def parse(self, response): for card in response.css("div[data-component-type='s-search-result']"): title = card.css("h2 a span::text").get() href = card.css("h2 a::attr(href)").get() if not title or not href: continue yield { "title": title.strip(), "url": response.urljoin(href), }
Führen Sie es aus und schreiben Sie die Items direkt in eine Datei mit Scrapys eingebautem Feed-Export, der alles serialisiert, was der Spider yieldet:
scrapy runspider myspider.py -o products.json
Das Flag -o products.json weist Scrapy an, jedes geyieldete Item in eine JSON-Datei zu schreiben. Lassen Sie das Flag weg und die Items werden stattdessen in Ihrer Konsole ausgegeben. So oder so entspricht jede Scraped from-Zeile im Log einem Produkt, und der abschließende Statistikbericht zeigt, wie viele Items der Lauf gesammelt hat.
Wie die Ausgabe aussieht
Jedes Item ist ein kleiner Datensatz mit den zwei Feldern, die Sie geyieldet haben. Die JSON-Datei ist eine Liste davon, bereit zum Laden in eine Datenbank, ein Notebook oder eine nachgelagerte Pipeline.
[ { "title": "Airtight Cold Brew Iced Coffee Maker and Tea Infuser with Spout, 1.0L", "url": "https://www.amazon.com/Airtight-Coffee-Maker-Infuser-Spout/dp/B01CTIYU60" }, { "title": "KitchenAid Cold Brew Coffee Maker, Brushed Stainless Steel", "url": "https://www.amazon.com/KitchenAid-KCM4212SX-Coffee-Brushed-Stainless/dp/B06XNVZDC7" } ]
Mehr als eine Seite crawlen
Eine Suchseite ist eine Demo. Ein echter Crawl folgt den Links, die Sie gerade gesammelt haben, oder läuft durch die nächsten Ergebnisseiten, und Scrapy ist genau dafür gebaut. Anstatt ein einfaches Dictionary zu yielden, yielden Sie einen scrapy.Request für jede URL, die Sie verfolgen möchten, routen ihn über buildURL zurück über die Crawling API und weisen ihm einen Callback zu, der die nächste Seite parst.
def parse(self, response): for card in response.css("div[data-component-type='s-search-result']"): href = card.css("h2 a::attr(href)").get() if href: product_url = response.urljoin(href) yield scrapy.Request( api.buildURL(product_url, {}), callback=self.parse_product, ) def parse_product(self, response): yield { "title": response.css("#productTitle::text").get(default="").strip(), "url": response.url, }
Scrapy stellt jede Anfrage, die Sie yielden, in die Warteschlange, ruft sie über seinen Downloader ab und ruft den passenden Callback für jede Response auf, sodass ein zweistufiger Crawl (Suchseite, dann jede Produktseite) nur zwei Parse-Methoden sind. Da jede Follow-up-Anfrage mit buildURL eingeschlossen ist, läuft sie auch über die Crawling API, was die IP-Rotation und das Rendering über den gesamten Crawl konsistent hält. Begrenzen Sie Crawls während des Testens mit Scrapy-Einstellungen wie CLOSESPIDER_ITEMCOUNT und fügen Sie eine höfliche Verzögerung mit DOWNLOAD_DELAY hinzu, damit Sie das Ziel nicht überlasten. Für Seiten, die ihre Auflistungen mit JavaScript zeichnen, übernimmt dasselbe Routing sie, sobald Sie Rendering anfordern; der Leitfaden zu crawl JavaScript websites behandelt, wann Sie das brauchen.
Unblockiert bleiben
Das Routing über die Crawling API übernimmt die zwei schwierigsten Teile, Rendering und eine vertrauenswürdige IP, aber einige Gewohnheiten halten jeden längeren Crawl gesund.
-
Anfragen dosieren. Setzen Sie einen
DOWNLOAD_DELAYund lassen Sie Scrapys AutoThrottle die Rate anpassen, anstatt Anfragen so schnell zu schicken, wie das Framework kann. Geschwindigkeit ist das, was einen Crawler auffallen lässt. - Auf Rotation vertrauen. Ein Pool von Residential-IPs verteilt Anfragen über viele echte Benutzeradressen, sodass keine einzelne ein Rate-Limit auslöst. Die Crawling API erledigt das für Sie; wenn Sie jemals Ihren eigenen Stack aufbauen, ist das der Teil, den Sie richtig hinbekommen müssen.
- Status-Codes lesen. Ein Crawl, der beginnt, Nicht-200-Antworten zurückzugeben, sagt Ihnen, dass die aktuelle Rate oder IP-Stufe nicht mehr ausreicht. Behandeln Sie das als Signal zum Zurückgehen, nicht als Rauschen, das Sie ignorieren.
Dieselben Muster gelten gut über Python hinaus. Wenn Sie den Ansatz in einer anderen Sprache vergleichen möchten, folgt die Anleitung zum build a web crawler in Java derselben Abruf-über-die-API-dann-Parse-Form mit einer anderen Toolchain.
Verantwortungsvoll crawlen
Bleiben Sie bei öffentlichen Daten, den Auflistungstiteln und Links, die jeder ohne Anmeldung sehen kann, und halten Sie sich von allem hinter Authentifizierung, persönlichen Informationen oder urheberrechtlich geschützten Medien fern, die Sie weitergeben wollen. Respektieren Sie die robots.txt und Nutzungsbedingungen jeder Seite, die die Grenze dessen setzen, was Sie sammeln dürfen und wie, und halten Sie Ihre Anfrateraten vernünftig, damit Sie nicht die Server von jemand anderem belasten. Wenn eine Seite eine offizielle API für die benötigten Daten anbietet, bevorzugen Sie diese: Es ist der sanktionierte Weg und üblicherweise der stabilere. Keines der hier beschriebenen Tools ändert diese Verpflichtungen; es macht nur den technischen Teil funktionieren.
Wichtigste Erkenntnisse
-
Scrapy gibt Ihnen das Crawling-Framework. Eine Spider-Unterklasse mit
start_urlsund einerparse-Methode ist der gesamte Kern, undscrapy runspiderführt ihn aus einer Datei aus. -
Leiten Sie jede Anfrage über die Crawling API. Wickeln Sie jede Ziel-URL mit
api.buildURLein, sodass die Anfrage über eine rotierende, vertrauenswürdige IP läuft und gerendert zurückkommt, anstatt die Seite von Ihrer Datacenter-Adresse aus zu treffen. -
Bestätigen Sie eine 200 bevor Sie parsen. Führen Sie den Spider zuerst ohne Parser aus; ein
Crawled (200)gegen den API-Endpunkt beweist, dass das Routing funktioniert, bevor Sie Selektoren berühren. - Mit CSS oder XPath extrahieren. Die Response stellt beides bereit; ordnen Sie jedes Feld einem dauerhaften Selektor zu, wappnen Sie sich gegen fehlende Treffer und erwarten Sie, dass Selektoren im Laufe der Zeit driften.
-
Verantwortungsvoll crawlen. Bleiben Sie bei öffentlichen Daten, respektieren Sie
robots.txtund Nutzungsbedingungen, dosieren Sie Ihre Anfragen und bevorzugen Sie eine offizielle API, wenn eine existiert.
Häufig gestellte Fragen
Warum Scrapy über die Crawling API routen statt direkt abzurufen?
Weil eine direkte Scrapy-Anfrage das Ziel von Ihrer eigenen IP aus trifft und das rohe, oft ungerenderte HTML bekommt. Auf belebten kommerziellen Seiten bedeutet das CAPTCHAs, Blockierungen oder eine leere JavaScript-Hülle. Das Routen über die Crawling API ruft die Seite hinter einer rotierenden Residential-IP ab und rendert sie bei Bedarf, sodass das HTML, das Scrapy erreicht, die fertige Seite ist, die Sie tatsächlich parsen können.
Was macht api.buildURL?
Es nimmt eine Ziel-URL und gibt die vollständige Crawling-API-Anfrage-URL dafür zurück, mit Ihrem Token und dem Ziel als Query-Parameter angehängt. Sie zeigen Scrapy auf die URL, die buildURL zurückgibt, und die API ruft das Ziel in Ihrem Auftrag ab. Es erspart Ihnen das manuelle Zusammensetzen von https://api.crawlbase.com/?token=...&url=... mit falscher Escape-Behandlung.
Brauche ich das normale Token oder das JavaScript-Token?
Das hängt vom Ziel ab. Wenn die Seite ihre Inhalte im anfänglichen HTML bereitstellt, reicht das normale Token. Wenn die Auflistungen erst erscheinen, nachdem das JavaScript der Seite ausgeführt wurde, benötigen Sie das JavaScript-Token, damit die API die Seite in einem echten Browser rendert, bevor sie zurückgegeben wird. Wenn Felder, die Sie im Browser sehen können, in Scrapy leer zurückkommen, ist das üblicherweise das Zeichen, zum JavaScript-Token zu wechseln.
Kann ich CSS- und XPath-Selektoren im selben Spider verwenden?
Ja. Jede Scrapy-Response stellt sowohl response.css(...) als auch response.xpath(...) bereit, und Sie können sie frei mischen, sogar Feld für Feld. CSS ist normalerweise kürzer für Klassen- und Attributtreffer, während XPath praktischer ist, um den Baum aufzugehen oder nach Text zu treffen. Verwenden Sie was für das jeweilige Feld lesbarer ist.
Wie crawle ich mehrere Seiten oder folge Links?
Yielden Sie einen scrapy.Request für jede URL, der Sie folgen möchten, anstatt ein einfaches Item, wickeln Sie diese URL mit api.buildURL ein, damit sie zurück über die Crawling API geht, und geben Sie ihr einen Callback, der die nächste Seite parst. Scrapy stellt jede Anfrage, die Sie yielden, in die Warteschlange und ruft sie ab, sodass ein Suchseite-dann-Produktseite-Crawl nur zwei Parse-Methoden sind. Begrenzen Sie den Lauf mit Einstellungen wie CLOSESPIDER_ITEMCOUNT beim Testen.
Meine Selektoren geben None zurück. Was hat sich geändert?
Fast sicher das Markup der Seite. Klassennamen und Container-Attribute ändern sich ohne Ankündigung, was jeden daran gebundenen Selektor bricht. Öffnen Sie eine Live-Seite in den Dev-Tools Ihres Browsers, untersuchen Sie das Element erneut, bevorzugen Sie dauerhafte Anker wie stabile data--Attribute, wo Sie können, und aktualisieren Sie den Selektor. Periodische Selektorwartung ist bei jedem Produktions-Crawler normal.
Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.
Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.

