Como usar um proxy com o Node Fetch e criar um Web Scraper

Mihnea-Octavian Manolache em 24 de abril de 2023

imagem do blogue

Em primeiro lugar, quando se constrói um web scraper, os proxies são definitivamente muito importantes. Em segundo lugar, node-fetch é um dos clientes HTTP JavaScript mais populares. Portanto, faz sentido combinar os dois e criar um web scraper.

É por isso que hoje vamos discutir como usar um proxy com node-fetch. E como bónus, vamos construir um web scraper em cima desta infraestrutura.

Portanto, até ao final deste artigo:

  • Terá uma sólida compreensão do funcionamento dos proxies na recolha de dados da Web
  • Aprenderá a integrar um proxy com o node-fetch
  • Terá um projeto adicionado à sua carteira pessoal

O que é um proxy e porquê utilizá-lo para a recolha de dados da Web?

Nas redes informáticas, os proxies actuam como "middlewares" entre um cliente e um servidor. A arquitetura de um servidor proxy é bastante complexa, mas, em termos gerais, é isto que acontece quando se utiliza um proxy:

  1. O utilizador "toca" no servidor proxy e especifica o destino (servidor) que está a tentar alcançar (scrape)
  2. O servidor proxy liga-se ao seu destino e obtém os resultados (os ficheiros HTML de um sítio Web, por exemplo)
  3. Em seguida, o servidor proxy devolve-lhe a resposta que obteve do servidor de destino
imagem do blogue

Nesta cadeia, o seu IP permanece oculto do servidor de destino, uma vez que nunca se liga realmente a ele. E essa é a principal razão pela qual os proxies são uma parte tão importante do web scraping. Eles "escondem" o endereço IP do web scraper, para que este não seja bloqueado pelos sistemas antibot.

Porquê utilizar o node-fetch para a recolha de dados da Web?

Se JavaScript é a sua linguagem de programação favorita, existem muitos clientes HTTP que pode utilizar para construir um web scraper. Entre os mais populares, estão axios, got e mais alguns listados aqui. Mas o node-fetch continua sendo um dos pacotes npm mais baixados, e há uma razão para isso.

Primeiro, é o primeiro pacote a implementar a API Fetch no Node JS. Depois, a partir da versão 17.5.0, a equipa do Node JS adicionou a API Fetch, para que não fosse necessária uma dependência de terceiros. Até hoje, na versão 19.3.0 do Node JS, o fetch ainda está marcado como experimental. Portanto, o node-fetch continua sendo a solução mais estável.

Especificamente para o scraping, o node-fetch é uma óptima ferramenta porque, como o nome indica, é utilizado para obter recursos de várias fontes. E essa é talvez a definição mais básica de scraping.

Como usar o node-fetch com proxies?

Resumindo, não há nenhum método embutido para usar um proxy com node-fetch. Por isso, se quiser construir um web scraper, mas a sua infraestrutura depende do node-fetch, pode correr o risco de expor o seu IP real. Isto significa que corre o risco de ser bloqueado por software antibot.

Felizmente, porém, existem soluções alternativas para isso. Uma delas nos foi oferecida por Nathan Rajlich, que construiu um módulo que implementa o http.Agent e é chamado de https-proxy-agent. A instalação está disponível via npm. Além disso, implementá-lo com node-fetch é bastante simples:

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 efeitos deste teste, utilizei um proxy gratuito do Proxy Scrape. Como esperado, a resposta indica que o pedido teve origem no IP do proxy, e não no meu IP local:

"origem": "1.255.134.136"

Outra opção é usar node-fetch-with-proxy. Este pacote usa o proxy-agent como uma dependência própria em cima do node-fetch. Para que isso funcione, tudo o que você precisa fazer é definir a variável de ambiente 'HTTP_PROXY'. Ela recebe o endereço IP do seu servidor proxy e o número da porta como um valor. Então você pode usar a sintaxe regular do node-fetch para fazer suas chamadas, que serão automaticamente encaminhadas para o servidor proxy. Aqui está um exemplo:

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

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

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

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

Como construir um web scraper usando um proxy com node-fetch?

Para terminar, já construímos um web scraper. Os exemplos de código acima fazem exatamente o que qualquer web scraper faz, ou seja, recolhem dados de um sítio Web. No entanto, num cenário da vida real, um web scraper é um pouco mais complexo. Por exemplo, os dados brutos precisam de ser processados, ou precisamos de verificar e analisar os cabeçalhos ou cookies recolhidos. Por isso, vamos aprofundar um pouco mais e transformar a nossa primeira amostra num verdadeiro raspador. Vamos definir algumas expectativas:

  1. Devemos ser capazes de devolver o HTML em bruto
  2. Devemos ser capazes de devolver toda a resposta como um objeto JSON
  3. Devemos ser capazes de extrair elementos com base em selectores específicos

Assumindo que já instalou o node-fetch e o https-proxy-agent, vamos precisar de mais uma coisa: um analisador HTML. Eu sempre escolho o cheerio para raspagem da web. Por isso, certifique-se de que o instala no seu projeto. Dito isto, vamos começar:

#1: Importar dependências

A primeira coisa que queremos fazer é importar os pacotes que discutimos acima. Acho que esta parte não precisa de mais explicações:

import fetch from 'node-fetch';

import HttpsProxyAgent from "https-proxy-agent";

import * as cheerio from 'cheerio';

#2: Lógica do raspador

Precisamos que o nosso raspador seja capaz de executar três acções: devolver o HTML da linha, devolver a resposta completa e devolver um elemento com base no seu seletor CSS. Uma delas já foi parcialmente implementada antes. Mas vamos dividir tudo em três funções:

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: Analisador de argumentos

Podemos usar argumentos de terminal para distinguir entre as três opções que implementámos no nosso raspador. Existem opções que podem ser usadas para analisar argumentos de terminal no Node, mas eu gosto de manter as coisas simples. É por isso que vamos usar process.argv, que gera um array de argumentos. Note que os dois primeiros itens deste array são 'node' e o nome do seu script. Por exemplo, se estivermos executando `node scraper.js raw_html`, o array de argumentos será parecido com este:

[

'/usr/local/bin/node',

'path_to_directory/scraper.js',

'raw_html'

]

Ignorando os dois primeiros elementos, utilizaremos a seguinte lógica:

  1. o primeiro argumento especificará a função que queremos executar;
  2. o segundo apontará para o nosso alvo (o sítio Web que queremos recolher);
  3. o terceiro apontará para o servidor proxy;
  4. e um quarto apontará para o seletor css.

Assim, o comando para executar o nosso raspador deve ter o seguinte aspeto:

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

Isso se traduz simplesmente em extrair o html bruto da página inicial do WebScrapingAPI e usar o http://1.255.134.136 como um middleware proxy. Agora a parte final é codificar a lógica para esses argumentos, de modo que nosso código entenda o comando run:

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

}

E é basicamente isso. Parabéns! Você criou com sucesso um web scraper totalmente funcional usando um proxy com node-fetch. Desafio-o agora a adicionar mais funcionalidades a este scraper, a fazer a sua própria versão e a usá-la como um ativo no seu portfólio pessoal.

Utilizar um proxy com node-fetch pode não ser suficiente para a recolha de dados da Web

Como gosto de dizer, a recolha furtiva de dados é mais do que esconder o seu endereço IP. Na realidade, utilizar um servidor proxy para o seu raspador da Web é apenas uma camada de proteção contra o software antibot. Outra camada é alterar o seu agente de utilizador [definindo cabeçalhos personalizados para o seu pedido] (LINK https://trello.com/c/n8xZswSI/14-2-8-january-article-13-http-headers-with-axios).

Na Web Scraping API, por exemplo, temos uma equipa dedicada que trabalha em técnicas de evasão personalizadas. Algumas delas vão até ao ponto de modificar os valores predefinidos do navegador sem cabeça para evitar a recolha de impressões digitais.

Além disso, como os sítios modernos processam o conteúdo dinamicamente utilizando JavaScript, um simples cliente HTTP como o node-fetch pode não ser suficiente. Você pode querer explorar o uso de um navegador da Web real. O selenium do Python ou o puppeteer do Node são apenas duas opções que você pode analisar nesse sentido.

Conclusões

Usar um proxy com node-fetch é um ótimo ponto de partida para construir um web scraper. No entanto, tem de ter em conta o facto de os dois não serem "diretamente compatíveis" e terá de utilizar uma solução de terceiros para os ligar. Felizmente, existem muitas possibilidades e a comunidade JavaScript está sempre disposta a ajudar os recém-chegados.

Construir um raspador furtivo é, no entanto, mais difícil e terás de inventar técnicas de evasão mais complexas. Mas eu gosto de ver uma oportunidade em tudo. Por que não pegar no que aprendeste hoje e acrescentar-lhe algo? Com sorte, no final, terás o melhor web scraper escrito com node-fetch e proxies. Como sempre, meu conselho é continuar aprendendo!

Notícias e actualizações

Mantenha-se atualizado com os mais recentes guias e notícias sobre raspagem da Web, subscrevendo a nossa newsletter.

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

Artigos relacionados

miniatura
GuiasSaiba como contornar a deteção do Cloudflare com o melhor navegador Selenium

Saiba qual é o melhor browser para contornar os sistemas de deteção Cloudflare enquanto faz web scraping com o Selenium.

Mihnea-Octavian Manolache
avatar do autor
Mihnea-Octavian Manolache
9 min. de leitura
miniatura
GuiasComo construir um raspador e descarregar um ficheiro com o Puppeteer

Descubra 3 formas de descarregar ficheiros com o Puppeteer e construa um web scraper que faz exatamente isso.

Mihnea-Octavian Manolache
avatar do autor
Mihnea-Octavian Manolache
8 min. de leitura
miniatura
GuiasComo extrair comentários do Google Maps na Web

Saiba como extrair comentários do Google Maps com a nossa API utilizando Node.js. Obtenha instruções passo a passo sobre a configuração, a extração de dados e a resolução de possíveis problemas.

Andrei Ogiolan
avatar do autor
Andrei Ogiolan
9 min. de leitura