Cómo utilizar un proxy con Node Fetch y crear un raspador web

Mihnea-Octavian Manolache el 24 abr 2023

blog-image

En primer lugar, cuando se construye un raspador web, los proxies son definitivamente muy importantes. En segundo lugar, node-fetch es uno de los clientes JavaScript HTTP más populares. Así que tiene sentido combinar los dos y crear un raspador web.

Es por eso que hoy vamos a discutir cómo utilizar un proxy con node-fetch. Y como un bono, vamos a construir un raspador web en la parte superior de esta infraestructura.

Así que al final de este artículo:

  • Tendrá una sólida comprensión de cómo funcionan los proxies en el web scraping
  • Aprenderás a integrar un proxy con node-fetch
  • Tendrá un proyecto añadido a su cartera personal

¿Qué es un proxy y por qué utilizarlo para el web scraping?

En redes informáticas, los proxies actúan como "middlewares" entre un cliente y un servidor. La arquitectura de un servidor proxy es bastante compleja, pero a grandes rasgos esto es lo que ocurre cuando se utiliza un proxy:

  1. Usted "pincha" en el servidor proxy y especifica el destino (servidor) al que intenta llegar (scrape)
  2. El servidor proxy se conecta a su objetivo y recupera los resultados (los archivos HTML de un sitio web, por ejemplo).
  3. A continuación, el servidor proxy le devuelve la respuesta que obtuvo del servidor de destino
blog-image

En esta cadena, tu IP permanece oculta para el servidor de destino, ya que en realidad nunca te conectas a él. Y esa es principalmente la razón principal por la que los proxies son una parte tan importante del web scraping. Ocultan" la dirección IP del web scraper para que no sea bloqueado por los sistemas antibot.

¿Por qué utilizar node-fetch para el web scraping?

Si JavaScript es tu lenguaje de programación favorito, hay muchos clientes HTTP que puedes utilizar para construir un raspador web. Entre los más populares, están axios, got y un par más listados aquí. Pero node-fetch sigue siendo uno de los paquetes npm más descargados, y hay una razón para ello.

En primer lugar, es el primer paquete que implementa la API Fetch en Node JS. Luego, a partir de la v17.5.0 el equipo de Node JS añadió la API Fetch, para que no fuera necesaria como dependencia de terceros. Aún hoy, en la versión 19.3.0 de Node JS, fetch sigue marcado como experimental. Así que node-fetch sigue siendo la solución más estable.

Específicamente para el scraping, node-fetch es una gran herramienta porque, como su nombre indica, se utiliza para obtener recursos de diversas fuentes. Y esa es quizá la definición más básica de scraping.

¿Cómo utilizar node-fetch con proxies?

En resumen, no hay un método integrado para usar un proxy con node-fetch. Así que si quieres construir un raspador web, pero tu infraestructura depende de node-fetch, entonces podrías arriesgarte a exponer tu IP real. Esto significa que te arriesgas a ser bloqueado por software antibot.

Afortunadamente, sin embargo, hay soluciones para ello. Una de ellas nos la ofrece Nathan Rajlich, que construyó un módulo que implementa http.Agent y se llama https-proxy-agent. La instalación está disponible a través de npm. Además, implementarlo con node-fetch es bastante sencillo:

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()

Para realizar esta prueba, he utilizado un proxy gratuito de Proxy Scrape. Como era de esperar, la respuesta indica que la solicitud se originó desde la IP del proxy, y no desde mi IP local:

"origen": "1.255.134.136"

Otra opción es utilizar node-fetch-with-proxy. Este paquete utiliza proxy-agent como una dependencia propia sobre node-fetch. Para que funcione, todo lo que tienes que hacer es establecer la variable de entorno 'HTTP_PROXY'. Toma como valor la dirección IP y el número de puerto de tu servidor proxy. A continuación, puede utilizar la sintaxis normal de node-fetch para realizar sus llamadas, que se dirigirán automáticamente al servidor proxy. He aquí un ejemplo:

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

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

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

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

¿Cómo construir un raspador web utilizando un proxy con node-fetch?

En una nota alta, ya hemos construido un raspador web. Los ejemplos de código de arriba hacen exactamente lo que cualquier web scraper hace, es decir, recogen datos de un sitio web. Sin embargo, en un escenario de la vida real, un web scraper es un poco más complejo. Por ejemplo, los datos en bruto necesitan ser procesados, o tenemos que comprobar y analizar las cabeceras o cookies recogidas. Así que vamos a profundizar un poco más y convertir nuestra primera muestra en un scraper real. Establezcamos algunas expectativas:

  1. Deberíamos poder devolver el HTML sin procesar
  2. Deberíamos poder devolver la respuesta completa como un objeto JSON
  3. Deberíamos poder extraer elementos basándonos en selectores específicos

Asumiendo que ya has instalado node-fetch y https-proxy-agent, necesitaremos una cosa más: un analizador HTML. Yo siempre uso cheerio para el web scraping. Así que asegúrate de instalarlo en tu proyecto. Dicho esto, empecemos:

#1: Importar dependencias

Lo primero que queremos hacer es importar los paquetes de los que hemos hablado antes. Supongo que esta parte no necesita más explicación:

import fetch from 'node-fetch';

import HttpsProxyAgent from "https-proxy-agent";

import * as cheerio from 'cheerio';

#2: Lógica del rascador

Necesitamos que nuestro scraper sea capaz de realizar tres acciones: devolver el HTML de la fila, devolver la respuesta completa y devolver un elemento basándose en su selector CSS. Una de ellas ya la hemos implementado parcialmente antes. Pero dividamos todo en tres funciones:

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: Analizador sintáctico de argumentos

Podemos usar argumentos terminales para distinguir entre las tres opciones que hemos implementado en nuestro scraper. Hay opciones que puedes usar para parsear argumentos terminales en Node, pero me gusta mantener las cosas simples. Por eso usaremos process.argv, que genera un array de argumentos. Ten en cuenta que los dos primeros elementos de este array son `node' y el nombre de tu script. Por ejemplo, si ejecutamos `node scraper.js raw_html`, el array de argumentos tendrá este aspecto:

[

'/usr/local/bin/node',

'path_to_directory/scraper.js',

'raw_html'

]

Ignorando los dos primeros elementos, utilizaremos la siguiente lógica:

  1. el primer argumento especificará la función que queremos ejecutar;
  2. el segundo apuntará a nuestro objetivo (el sitio web que queremos raspar);
  3. el tercero apuntará al servidor proxy;
  4. y un cuarto apuntará al selector css.

Así que el comando para ejecutar nuestro scraper debería tener este aspecto:

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

Esto se traduce simplemente en extraer el html en bruto de la página de inicio de WebScrapingAPI y utilizar http://1.255.134.136 como middleware proxy. Ahora la parte final es codificar la lógica para estos argumentos, de tal manera que nuestro código entienda el comando run:

const ACTION = proceso.argv[2]

const TARGET = proceso.argv[3]

const PROXY = proceso.argv[4]

const SELECTOR = proceso.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`')

}

Y eso es todo. Enhorabuena. Has creado con éxito un raspador web completamente funcional usando un proxy con node-fetch. Ahora te reto a que añadas más funcionalidad a este scraper, hagas tu propia versión, y lo utilices como un activo en tu portafolio personal.

Utilizar un proxy con node-fetch puede no ser suficiente para el web scraping

Como me gusta decir, el raspado sigiloso es mucho más que ocultar la dirección IP. En realidad, el uso de un servidor proxy para su raspador web es sólo una capa de protección contra el software antibot. Otra capa es cambiar tu agente de usuario [estableciendo cabeceras personalizadas en tu solicitud] (LINK https://trello.com/c/n8xZswSI/14-2-8-january-article-13-http-headers-with-axios).

En Web Scraping API, por ejemplo, tenemos un equipo dedicado que trabaja en técnicas de evasión personalizadas. Algunas de ellas van tan lejos como modificar los valores por defecto del navegador headless para evitar el fingerprinting.

Por otra parte, como los sitios modernos renderizan el contenido dinámicamente usando JavaScript, un simple cliente HTTP como node-fetch puede no ser suficiente. Es posible que desee explorar el uso de un navegador web real. El selenium de Python o el puppeteer de Node son dos opciones que podrías considerar en este sentido.

Conclusiones

Utilizar un proxy con node-fetch es un buen punto de partida para crear un raspador web. Sin embargo, hay que tener en cuenta el hecho de que los dos no son "directamente compatibles" y tendrás que utilizar una solución de terceros para vincularlos. Por suerte, hay muchas posibilidades y la comunidad JavaScript siempre está dispuesta a ayudar a los recién llegados.

Sin embargo, construir un rascador sigiloso es más difícil y tendrás que idear técnicas de evasión más complejas. Pero me gusta ver una oportunidad en todo. ¿Por qué no tomas lo que has aprendido hoy y lo amplías? Con suerte, al final, tendrás el mejor web scraper escrito con node-fetch y proxies. Como siempre, mi consejo es que sigas aprendiendo.

Noticias y actualidad

Manténgase al día de las últimas guías y noticias sobre raspado web suscribiéndose a nuestro boletín.

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Artículos relacionados

miniatura
GuíasAprenda a eludir la detección de Cloudflare con el mejor navegador Selenium

Conozca cuál es el mejor navegador para eludir los sistemas de detección de Cloudflare mientras hace web scraping con Selenium.

Mihnea-Octavian Manolache
avatar de autor
Mihnea-Octavian Manolache
9 min leer
miniatura
GuíasCómo construir un rascador y descargar un archivo con Puppeteer

Descubra 3 maneras de descargar archivos con Puppeteer y construya un raspador web que haga exactamente eso.

Mihnea-Octavian Manolache
avatar de autor
Mihnea-Octavian Manolache
8 min leer
miniatura
GuíasCómo extraer reseñas de Google Maps

Aprende a extraer opiniones de Google Maps con nuestra API utilizando Node.js. Obtén instrucciones paso a paso para configurar, extraer datos y superar posibles problemas.

Andrei Ogiolan
avatar de autor
Andrei Ogiolan
9 min leer