Volver al blog
Guías
Mihnea-Octavian ManolacheLast updated on Mar 31, 20267 min read

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

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

En primer lugar, a la hora de crear un rastreador web, los proxies son sin duda muy importantes. En segundo lugar, node-fetch es uno de los clientes HTTP de JavaScript más populares. Por eso, tiene sentido combinar ambos para crear un rastreador web.

Por eso, hoy vamos a hablar de cómo usar un proxy con node-fetch. Y, como extra, crearemos un rastreador web sobre esta infraestructura.

Así que, al final de este artículo:

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

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

En redes informáticas, los proxies actúan como «intermediarios» 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 utilizas un proxy:

  • Te «conectas» al servidor proxy y especificas el destino (servidor) al que intentas llegar (scrape)
  • El servidor proxy se conecta a tu destino y recupera los resultados (los archivos HTML de un sitio web, por ejemplo)
  • A continuación, el servidor proxy te devuelve la respuesta que ha recibido del servidor de destino

En esta cadena, tu IP permanece oculta al servidor de destino, ya que en realidad nunca te conectas a él. Y esa es, principalmente, la razón por la que los proxies son una parte tan importante del web scraping. «Ocultar» la dirección IP del web scraper, para que no sea bloqueada 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 crear un scraper web. Entre los más populares se encuentran axios, got y algunos más que se enumeran 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 en implementar la API Fetch en Node.js. Posteriormente, a partir de la versión 17.5.0, el equipo de Node.js añadió la API Fetch, por lo que ya no sería necesaria como dependencia de terceros. A día de hoy, en la versión 19.3.0 de Node.js, fetch sigue marcado como experimental. Por lo tanto, node-fetch sigue siendo la solución más estable.

En lo que respecta específicamente al scraping, node-fetch es una herramienta estupenda porque, como su nombre indica, se utiliza para obtener recursos de diversas fuentes. Y esa es quizás la definición más básica de scraping.

¿Cómo se utiliza node-fetch con proxies?

En resumen, no existe un método integrado para utilizar un proxy con node-fetch. Por lo tanto, si quieres crear un scraper web, pero tu infraestructura se basa en node-fetch, corres el riesgo de exponer tu IP real. Esto significa que te arriesgas a que te bloquee un software antibots.

Por suerte, sin embargo, hay soluciones alternativas. Una de ellas nos la ofrece Nathan Rajlich, quien creó 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 esta prueba, utilicé 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:

"origin": "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 esto funcione, lo único que hay que hacer es configurar 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, puedes utilizar la sintaxis habitual de node-fetch para realizar tus llamadas, que se redirigirán automáticamente al servidor proxy. Aquí tienes 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 crear un rastreador web utilizando un proxy con node-fetch?

Por suerte, ya hemos creado un rastreador web. Los ejemplos de código anteriores hacen exactamente lo que hace cualquier rastreador web: recopilan datos de un sitio web. Sin embargo, en la vida real, un rastreador web es un poco más complejo. Por ejemplo, hay que procesar los datos sin procesar, o debemos comprobar y analizar los encabezados o las cookies recopilados. Así que profundicemos un poco más y convirtamos nuestro primer ejemplo en un rastreador real. Establezcamos algunas expectativas:

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

Suponiendo que ya tienes instalados node-fetch y https-proxy-agent, necesitaremos una cosa más: un analizador de HTML. Yo siempre utilizo 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 que hemos comentado anteriormente. 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 scraper

Necesitamos que nuestro scraper sea capaz de realizar tres acciones: devolver el HTML de la fila, devolver la respuesta completa y devolver un elemento basado 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 de argumentos

Podemos usar los argumentos de la terminal para distinguir entre las tres opciones que hemos implementado en nuestro scraper. Hay opciones que puedes usar para analizar los argumentos de la terminal en Node, pero me gusta mantener las cosas sencillas. Por eso usaremos process.argv, que genera una matriz de argumentos. Ten en cuenta que los dos primeros elementos de esta matriz son «node» y el nombre de tu script. Por ejemplo, si ejecutas `node scraper.js raw_html`, la matriz 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:

  • el primer argumento especificará la función que queremos ejecutar;
  • el segundo apuntará a nuestro objetivo (el sitio web que queremos rastrear);
  • el tercero apuntará al servidor proxy;
  • y el cuarto apuntará al selector CSS.

Así pues, el comando para ejecutar nuestro rastreador debería tener este aspecto:

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

Esto simplemente significa extraer el HTML sin procesar de la página de inicio de WebScrapingAPI y utilizar http://1.255.134.136 como middleware de proxy. Ahora, la parte final consiste en programar la lógica para estos argumentos, de modo que nuestro código entienda el comando de ejecución:

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`')

}

Y eso es básicamente todo. ¡Enhorabuena! Has creado con éxito un rastreador web totalmente funcional utilizando un proxy con node-fetch. Ahora te reto a que añadas más funcionalidades a este rastreador, crees tu propia versión y la utilices como un activo en tu portafolio personal.

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

Como suelo decir, el scraping sigiloso implica mucho más que simplemente ocultar tu dirección IP. En realidad, utilizar un servidor proxy para tu scraper web es solo una capa de protección contra el software antibots. Otra capa consiste en cambiar tu agente de usuario [configurando encabezados personalizados en tu solicitud] (ENLACE https://trello.com/c/n8xZswSI/14-2-8-january-article-13-http-headers-with-axios).

En Web Scraping API, por ejemplo, contamos con un equipo dedicado que trabaja en técnicas de evasión personalizadas. Algunas de ellas llegan incluso a modificar los valores predeterminados del navegador sin interfaz gráfica para evitar el fingerprinting.

Además, dado que los sitios web modernos renderizan el contenido de forma dinámica utilizando JavaScript, un simple cliente HTTP como node-fetch puede no ser suficiente. Quizás te interese explorar el uso de un navegador web real. Selenium de Python o Puppeteer de Node son solo dos opciones que podrías considerar en ese sentido.

Conclusiones

Usar un proxy con node-fetch es un excelente punto de partida a la hora de crear un rastreador web. Sin embargo, debes tener en cuenta que ambos no son «directamente compatibles» y que tendrás que utilizar una solución de terceros para conectarlos. Por suerte, hay muchas posibilidades y la comunidad de JavaScript siempre está dispuesta a ayudar a los principiantes.

Crear un scraper sigiloso es, sin embargo, 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 aprovechas lo que has aprendido hoy y lo amplías? Con suerte, al final, habrás creado el mejor scraper web escrito con node-fetch y proxies. Como siempre, mi consejo para ti es que sigas aprendiendo.

Acerca del autor
Mihnea-Octavian Manolache, Desarrollador Full Stack @ WebScrapingAPI
Mihnea-Octavian ManolacheDesarrollador Full Stack

Mihnea-Octavian Manolache es ingeniero Full Stack y DevOps en WebScrapingAPI, donde se encarga de desarrollar funciones para los productos y de mantener la infraestructura que garantiza el buen funcionamiento de la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.