Zurück zum Blog
Anleitungen
Mihnea-Octavian Manolache24. April 20238 Minuten Lesezeit

So verwenden Sie einen Proxy mit Node Fetch und erstellen einen Web-Scraper

So verwenden Sie einen Proxy mit Node Fetch und erstellen einen Web-Scraper

Was ist ein Proxy und warum wird er beim Web-Scraping verwendet?

In Computernetzwerken fungieren Proxys als „Middleware“ zwischen einem Client und einem Server. Die Architektur eines Proxy-Servers ist recht komplex, aber auf einer allgemeinen Ebene geschieht Folgendes, wenn Sie einen Proxy verwenden:

  • Sie „schalten“ sich in den Proxy-Server ein und geben das Ziel (den Server) an, das Sie erreichen (scrapen) möchten
  • Der Proxy-Server stellt eine Verbindung zu Ihrem Ziel her und ruft die Ergebnisse ab (zum Beispiel die HTML-Dateien einer Website)
  • Der Proxy-Server leitet dann die Antwort, die er vom Zielserver erhalten hat, an Sie weiter
Diagram showing a scraper routing requests through a proxy to a target website

In dieser Kette bleibt Ihre IP-Adresse vor dem Zielserver verborgen, da Sie nie tatsächlich eine Verbindung zu ihm herstellen. Und das ist im Wesentlichen der Hauptgrund, warum Proxys ein so wichtiger Bestandteil des Web-Scrapings sind. Sie „verbergen“ die IP-Adresse des Web-Scrapers, sodass dieser nicht von Anti-Bot-Systemen blockiert wird.

Warum node-fetch für das Web-Scraping verwenden?

Wenn JavaScript Ihre bevorzugte Programmiersprache ist, gibt es viele HTTP-Clients, die Sie zum Erstellen eines Webscrapers verwenden können. Zu den beliebtesten gehören axios, got und einige weitere, die hier aufgelistet sind. Aber node-fetch bleibt eines der am häufigsten heruntergeladenen npm-Pakete, und dafür gibt es einen Grund.

Erstens ist es das erste Paket, das die Fetch-API in Node.js implementiert hat. Ab Version 17.5.0 hat das Node.js-Team dann die Fetch-API integriert, sodass sie nicht mehr als Abhängigkeit von Drittanbietern benötigt wurde. Bis heute, in Node.js Version 19.3.0, ist fetch jedoch immer noch als experimentell gekennzeichnet. Daher bleibt node-fetch die stabilere Lösung.

Speziell für das Scraping ist node-fetch ein großartiges Tool, da es, wie der Name schon sagt, dazu dient, Ressourcen aus verschiedenen Quellen abzurufen. Und das ist vielleicht die grundlegendste Definition von Scraping.

Wie verwendet man Node-Fetch mit Proxys?

Kurz gesagt: Es gibt keine integrierte Methode, um einen Proxy mit node-fetch zu verwenden. Wenn Sie also einen Web-Scraper erstellen möchten, Ihre Infrastruktur aber auf node-fetch basiert, riskieren Sie möglicherweise, Ihre echte IP-Adresse preiszugeben. Das bedeutet, dass Sie Gefahr laufen, von Anti-Bot-Software blockiert zu werden.

Glücklicherweise gibt es jedoch Workarounds dafür. Einen davon bietet uns Nathan Rajlich an, der ein Modul entwickelt hat, das http.Agent implementiert und https-proxy-agent heißt. Die Installation ist über npm verfügbar. Auch die Implementierung mit node-fetch ist ziemlich unkompliziert:

import fetch from 'node-fetch';

import HttpsProxyAgent from "https-proxy-agent";

const fetch_proxy = async () => {

   	const proxy = new HttpsProxyAgent('http://1.255.134.136:3128');

   	const response = await fetch('https://httpbin.org/ip', { agent: proxy});

   	const data = await response.text();

   	console.log(data);

}

fetch_proxy()

Für diesen Test habe ich einen kostenlosen Proxy von Proxy Scrape verwendet. Wie erwartet zeigt die Antwort, dass die Anfrage von der Proxy-IP stammt und nicht von meiner lokalen IP:

"origin": "1.255.134.136"

Eine weitere Option ist die Verwendung von node-fetch-with-proxy. Dieses Paket nutzt proxy-agent als eigene Abhängigkeit zusätzlich zu node-fetch. Damit dies funktioniert, müssen Sie lediglich die Umgebungsvariable „HTTP_PROXY“ setzen. Als Wert werden die IP-Adresse und die Portnummer Ihres Proxy-Servers verwendet. Anschließend können Sie die reguläre node-fetch-Syntax für Ihre Aufrufe verwenden, die automatisch an den Proxy-Server weitergeleitet werden. Hier ein Beispiel:

import fetch from "node-fetch-with-proxy";

fetch('http://httpbin.org/ip')

.then(res => res.json())

.then(json => console.log(json));

Wie erstellt man einen Web-Scraper mit einem Proxy unter Verwendung von node-fetch?

Positiv zu vermerken ist, dass wir bereits einen Web-Scraper erstellt haben. Die obigen Code-Beispiele tun genau das, was jeder Web-Scraper tut, nämlich Daten von einer Website sammeln. In der Praxis ist ein Web-Scraper jedoch etwas komplexer. Beispielsweise müssen die Rohdaten verarbeitet werden, oder wir müssen die gesammelten Header oder Cookies überprüfen und analysieren. Tauchen wir also etwas tiefer ein und verwandeln wir unser erstes Beispiel in einen echten Scraper. Legen wir zunächst einige Erwartungen fest:

  • Wir sollten in der Lage sein, den Roh-HTML-Code zurückzugeben
  • Wir sollten in der Lage sein, die gesamte Antwort als JSON-Objekt zurückzugeben
  • Wir sollten in der Lage sein, Elemente anhand bestimmter Selektoren zu extrahieren

Angenommen, Sie haben node-fetch und https-proxy-agent bereits installiert, benötigen wir noch eine weitere Sache: einen HTML-Parser. Ich verwende für das Web-Scraping immer cheerio. Stellen Sie also bitte sicher, dass Sie es in Ihrem Projekt installieren. Nachdem das geklärt ist, lassen Sie uns loslegen:

#1: Abhängigkeiten importieren

Als Erstes wollen wir die oben besprochenen Pakete importieren. Ich denke, dieser Teil bedarf keiner weiteren Erklärung:

import fetch from 'node-fetch';

import HttpsProxyAgent from "https-proxy-agent";

import * as cheerio from 'cheerio';

#2: Scraper-Logik

Unser Scraper muss drei Aktionen ausführen können: den HTML-Code der Zeile zurückgeben, die gesamte Antwort zurückgeben und ein Element basierend auf seinem CSS-Selektor zurückgeben. Eine davon haben wir bereits teilweise implementiert. Aber lassen Sie uns alles in drei Funktionen aufteilen:

const raw_html = async (proxyServer, targetURL) => {

   const proxy = new HttpsProxyAgent(proxyServer);

   const response = await fetch(targetURL, { agent: proxy});

   const data = await response.text();

   return data;

}

const json_response = async (proxyServer, targetURL) => {

   const proxy = new HttpsProxyAgent(proxyServer);

   const response = await fetch(targetURL, { agent: proxy});

   const data = {

       url: response.url,

       status: response.status,

       Headers: response.headers,

       body: await response.text()

   }

   return data;

}

const select_css = async (proxyServer, targetURL, cssSelector) => {

   const proxy = new HttpsProxyAgent(proxyServer);

   const response = await fetch(targetURL, { agent: proxy});

   const html = await response.text();

   const $ = cheerio.load(html);

   return $(cssSelector).text();

}

#3: Argument-Parser

Wir können Terminalargumente verwenden, um zwischen den drei Optionen zu unterscheiden, die wir in unserem Scraper implementiert haben. Es gibt Optionen, mit denen man Terminalargumente in Node parsen kann, aber ich halte die Dinge gerne einfach. Deshalb verwenden wir `process.argv`, das ein Array von Argumenten generiert. Beachte, dass die ersten beiden Elemente dieses Arrays „node“ und der Name deines Skripts sind. Wenn du beispielsweise `node scraper.js raw_html` ausführst, sieht das Argumente-Array wie folgt aus:

[

  '/usr/local/bin/node',

  'path_to_directory/scraper.js',

  'raw_html'

]

Wenn wir die ersten beiden Elemente ignorieren, verwenden wir die folgende Logik:

  • Das erste Argument gibt die Funktion an, die wir ausführen möchten;
  • das zweite verweist auf unser Ziel (die Website, die wir scrapen möchten);
  • das dritte verweist auf den Proxy-Server;
  • und das vierte verweist auf den CSS-Selektor.

Der Befehl zum Ausführen unseres Scrapers sollte also wie folgt aussehen:

~ » node scraper.js raw_html https://webscrapingapi.com http://1.255.134.136:3128 

Dies bedeutet einfach, dass der Roh-HTML-Code von der Startseite der WebScrapingAPI extrahiert und http://1.255.134.136 als Proxy-Middleware verwendet wird. Nun besteht der letzte Schritt darin, die Logik für diese Argumente zu programmieren, damit unser Code den Ausführungsbefehl versteht:

const ACTION = process.argv[2]

const TARGET = process.argv[3]

const PROXY = process.argv[4]

const SELECTOR = process.argv[5]
switch (ACTION) {

   case 'raw_html':

console.log(await raw_html(PROXY, TARGET))

break

   case 'json_response':

console.log(await json_response(PROXY, TARGET))

break

   case 'select_css':

SELECTOR ? console.log(await select_css(PROXY, TARGET, SELECTOR)) : console.log('Please specify a CSS selector!')

break

   default:

conssole.log('Please choose between `raw_html`, `json_response` and `select_css`')

}

Und das war’s im Grunde schon. Herzlichen Glückwunsch! Du hast erfolgreich einen voll funktionsfähigen Web-Scraper unter Verwendung eines Proxys mit node-fetch erstellt. Ich fordere dich nun heraus, diesem Scraper weitere Funktionen hinzuzufügen, deine eigene Version zu erstellen und sie als Teil deines persönlichen Portfolios zu nutzen.

Die Verwendung eines Proxys mit node-fetch reicht für das Web-Scraping möglicherweise nicht aus

Wie ich gerne sage: Zu einem unauffälligen Scraping gehört mehr als nur das Verbergen Ihrer IP-Adresse. In Wirklichkeit ist die Verwendung eines Proxy-Servers für Ihren Web-Scraper nur eine Schutzebene gegen Anti-Bot-Software. Eine weitere Schutzebene besteht darin, deinen User-Agent zu ändern, indem du [benutzerdefinierte Header für deine Anfrage festlegst] (LINK https://trello.com/c/n8xZswSI/14-2-8-january-article-13-http-headers-with-axios).

Bei Web Scraping API beispielsweise haben wir ein spezielles Team, das an benutzerdefinierten Umgehungstechniken arbeitet. Einige davon gehen so weit, dass sie die Standardwerte des Headless-Browsers ändern, um Fingerprinting zu vermeiden.

Da moderne Websites Inhalte zudem dynamisch mit JavaScript rendern, reicht ein einfacher HTTP-Client wie node-fetch möglicherweise nicht aus. Sie sollten die Verwendung eines echten Webbrowsers in Betracht ziehen. Python’s Selenium oder Node’s Puppeteer sind nur zwei Optionen, die Sie in diesem Zusammenhang prüfen könnten.

Fazit

Die Verwendung eines Proxys mit Node-Fetch ist ein guter Ausgangspunkt für die Entwicklung eines Web-Scrapers. Sie müssen jedoch berücksichtigen, dass die beiden nicht „direkt kompatibel“ sind und Sie eine Drittanbieterlösung nutzen müssen, um sie miteinander zu verbinden. Glücklicherweise gibt es zahlreiche Möglichkeiten, und die JavaScript-Community hilft Neulingen gerne weiter.

Die Entwicklung eines unauffälligen Scrapers ist jedoch schwieriger und erfordert komplexere Techniken zur Umgehung von Erkennungsmechanismen. Aber ich sehe in allem eine Chance. Warum nicht das, was du heute gelernt hast, als Grundlage nutzen und darauf aufbauen? Hoffentlich hast du am Ende den besten Web-Scraper entwickelt, der mit Node-Fetch und Proxys geschrieben wurde. Wie immer lautet mein Rat an dich: Lerne weiter!

Über den Autor
Mihnea-Octavian Manolache, Full-Stack-Entwickler @ WebScrapingAPI
Mihnea-Octavian ManolacheFull-Stack-Entwickler

Mihnea-Octavian Manolache ist Full-Stack- und DevOps-Entwickler bei WebScrapingAPI. Er entwickelt Produktfunktionen und sorgt für die Wartung der Infrastruktur, die den reibungslosen Betrieb der Plattform gewährleistet.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.