Voltar ao blogue

Desbloqueador de nós para web scraping

Desbloqueador de nós para web scraping

Todos nós detestamos aqueles momentos em que tentamos aceder a uma página e o site bloqueia o nosso pedido sem motivo aparente. O bloqueio geográfico, por exemplo, só pode ser contornado utilizando um proxy. 

O Node-Unblocker ajuda-nos a criar um proxy personalizado e a tê-lo a funcionar em poucos minutos.

O que é o Node-Unblocker?

O Node-Unblocker é uma biblioteca de uso geral para criar um proxy web, interceptar e alterar pedidos e respostas. 

Esta biblioteca também é utilizada em web scraping para contornar restrições implementadas pelo site, como o bloqueio geográfico, ocultar o endereço IP e limitar a taxa de pedidos, ou para enviar tokens de autenticação. 

Resumindo, ao utilizar esta biblioteca, pode dizer adeus ao conteúdo bloqueado e censurado.

Neste artigo, criamos uma aplicação Express com um proxy personalizado utilizando o Node Unblocker, adicionamos um middleware que altera o agente do utilizador para cada pedido, discutimos as limitações do proxy, implementamo-lo no Heroku e comparamo-lo com um serviço gerido como o WebScrapingAPI.

Pré-requisitos

Antes de começarmos, certifique-se de que tem a versão mais recente do Node.JS instalada. A instalação do Node.JS para cada plataforma (Windows, Linux, Mac) seria tema de um artigo separado, por isso, em vez de entrar em detalhes, consulte o site oficial e siga as instruções.

Configurar tudo

Começamos por criar um diretório para o nosso projeto chamado unblocked e inicializamos um projeto Node.JS dentro dele:

mkdir unblocked
cd unblocked
npm init

Instalar dependências

Para esta aplicação, instalamos duas bibliotecas: Express, um framework minimalista para o Node.JS, e o Node Unblocker.

npm install express unblocker

Criar a aplicação base

Criar a aplicação Express

Como o node.unblocker é executado dentro de uma instância do Express, temos de configurar o exemplo Hello World na nossa aplicação.

Crie um ficheiro index.js e cole o seguinte código:

const express = require('express') const app = express() const port = 8080 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(process.env.PORT || 8080, () => { console.log(`Example app listening on port ${port}`) })

Podemos executar a aplicação com este comando:

node index.js

Se acedermos a http://localhost:8080, veremos uma mensagem «Hello World». Isto significa que a nossa aplicação está a funcionar.

Adicionar o Node Unblocker ao Express

É hora de importar a biblioteca Node Unblock para a nossa aplicação:

var Unblocker = require('unblocker')

Criamos uma instância do Node Unblocker e passamos o parâmetro proxy. Pode encontrar a lista completa de parâmetros disponíveis aqui.

var unblocker = new Unblocker({prefix: '/proxy/'})

Registamos a biblioteca Node Unblocker no Express como um middleware para que as solicitações sejam interceptadas:

app.use(unblocker)

Atualizamos o listener da aplicação Express para adicionar suporte a websockets:

app.listen(process.env.PORT || 8080, () => { console.log(`Example app listening on port ${port}`) }).on('upgrade', unblocker.onUpgrade)

Depois de seguir todos estes passos, a nossa aplicação deverá ter este aspeto:

const express = require('express') const Unblocker = require('unblocker') const app = express() const port = 8080 const unblocker = new Unblocker({prefix: '/proxy/'}) app.use(unblocker) app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(process.env.PORT || 8080, () => { console.log(`Example app listening on port ${port}`) }).on('upgrade', unblocker.onUpgrade)

Testar o proxy

Reinicie a aplicação e aceda ao seguinte URL no seu navegador:

http://localhost:8080/proxy/https://webscrapingapi.com

Para garantir que o proxy funciona como esperado, abrimos as Ferramentas de Desenvolvedor no navegador e verificamos o separador Rede. Todas as solicitações devem passar pelo proxy.

Para quaisquer problemas que o proxy possa apresentar, recomenda-se ativar o modo de depuração definindo a variável de ambiente DEBUG. Use este comando para iniciar o proxy no modo de depuração:

DEBUG=unblocker:* node index.js

Nunca é boa ideia ativar isto em produção, por isso vamos mantê-lo apenas para o ambiente de desenvolvimento.

Utilização de middlewares

O Nodeunblocker não é apenas uma solução de proxy personalizada, mas permite a interceção e alteração de pedidos de saída e de entrada através de middleware.

Podemos usar esta funcionalidade para bloquear o carregamento de recursos específicos com base no tipo de recurso ou domínio, atualizar o agente do utilizador, substituir o conteúdo devolvido ou injetar tokens de autenticação nos cabeçalhos das solicitações.

Pode encontrar uma lista completa de exemplos aqui.

Vamos começar por criar um middleware para definir um agente de utilizador personalizado. Crie um ficheiro chamado user-agent.js e adicione este código ao mesmo:

module.exports = function(userAgent) {
    function setUserAgent(data) {
        data["headers"]["user-agent"] = userAgent
    }
    return setUserAgent
}

Esta função aceita o agente de utilizador personalizado com o parâmetro userAgent e regista-o no objeto de dados utilizando a função setUserAgent. O Node Unblocked chamará a função setUserAgent em cada pedido.

const userAgent = require('./user-agent')

Definimos o parâmetro requestMiddleware no construtor do Unblocker e estamos prontos para avançar.

const unblocker = new Unblocker({
    prefix: '/proxy/',
    requestMiddleware: [userAgent("nodeunblocker/1.5")]
})

O nosso ficheiro index.js deve ficar assim:

const express = require('express')
const Unblocker = require('unblocker')
const userAgent = require('./user-agent')
const app = express()
const port = 8080

const unblocker = new Unblocker({
    prefix: '/proxy/',
    requestMiddleware: [userAgent("nodeunblocker/1.5")]
})

app.use(unblocker)

app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(process.env.PORT || 8080, () => {
    console.log(`Example app listening on port ${port}`)
}).on('upgrade', unblocker.onUpgrade)

É hora de verificar se o nosso código funciona. Temos de alterar o URL do node-unblocker para garantir que os cabeçalhos são atualizados corretamente. 

Reinicie a aplicação e abra esta URL no seu navegador:

http://localhost:8080/proxy/https://www.whatsmyua.info/

Se o site exibir nodeunblocker/1.5, o nosso middleware funciona.

Implantar no Heroku

Com o nosso proxy em funcionamento, é hora de o implementar no Heroku, uma plataforma como serviço (PaaS) que nos permite criar, lançar e gerir aplicações totalmente na nuvem.

Tenha em mente que nem todos os fornecedores permitem proxies e aplicações de web scraping na sua infraestrutura. O Heroku aceita este tipo de aplicações, desde que as regras do robots.txt não sejam ignoradas.

Com a parte legal discutida, vamos preparar o nosso projeto para a implementação.

Script e motor

Temos de definir o script de arranque e os motores no ficheiro package.json.

A propriedade `engines` indica ao Heroku que precisamos da versão mais recente do Node.JS 16 instalada no nosso ambiente. O script de inicialização é executado quando o ambiente está configurado e a nossa aplicação está pronta para ser executada.

O nosso package.json deve ficar assim:

{
  "name": "unblocked",
  "version": "1.0.0",
  "main": "index.js",
  "engines": {
    "node": "16.x"
  },
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.1",
    "unblocker": "^2.3.0"
  }
}

O Heroku tornou a implementação de uma aplicação Node.JS uma maravilha. Antes de passar para a próxima secção, certifique-se de que instalou a CLI do Heroku e as ferramentas git.

Início de sessão e configuração

Use este comando para se autenticar no Heroku a partir do seu terminal local:

heroku login

Crie uma nova aplicação Heroku executando este comando:

heroku apps:create

Este comando irá devolver o ID da aplicação e um repositório git. Vamos usar o ID para definir a origem remota do nosso repositório:

git init
heroku git:remote -a [YOUR_APP_ID]

Como nunca é boa ideia incluir a pasta node_modules no controlo de versões, vamos criar um ficheiro .gitignore e adicionar a pasta a ele.

Implantação

O último passo antes de o nosso código chegar à produção é submetê-lo e implementá-lo. Vamos adicionar todos os ficheiros, criar uma submissão e fundir o ramo master no ramo do Heroku.

git add .
git commit -am "Initial commit"
git push heroku master

Após alguns segundos, a aplicação será implementada no Heroku. Parabéns! Está na hora de aceder à mesma no nosso navegador e verificar se funciona.

Use a seguinte estrutura de URL para construir a URL do Heroku:

[HEROKU_DYNO_URL]/proxy/https://webscrapingapi.com

Se se esqueceu ou perdeu a URL do Dyno, pode usar este comando para obter as informações disponíveis sobre a aplicação atual:

heroku info

Limitações

A facilidade de configuração deste proxy personalizado tem uma ressalva: funciona bem apenas para sites simples e falha em tarefas avançadas. Algumas dessas limitações são impossíveis de superar e exigirão o uso de uma biblioteca diferente ou de serviços de terceiros.

Um serviço gerido como o WebScrapingAPI implementa correções para todas estas limitações e adiciona algumas funcionalidades extra, como resolução automática de captchas, proxies residenciais e evasões avançadas para impedir que serviços como o Akamai, o Cloudflare e o Datadome detetem o seu pedido. 

Aqui está uma lista de limitações que deve ter em conta antes de pensar em utilizar o Node Unblocker no seu projeto de produção.

Problemas com OAuth

O OAuth é o padrão de autenticação preferido por sites modernos como o Facebook, Google, Youtube, Instagram e Twitter. Qualquer biblioteca que utilize o postMessage não funcionará com o Node Unblocker e, como talvez já tenha adivinhado, o OAuth requer o postMessage para funcionar corretamente.

Se quiser abdicar de 57% do tráfego da Internet apenas para utilizar esta biblioteca, pode avançar e adicioná-la ao seu projeto.

Sites complexos

Sites como o YouTube, HBO Max, Roblox, Discord e Instagram não funcionam e não há prazo para o lançamento de uma versão que permita que estes sites funcionem. 

A comunidade é convidada a contribuir com patches para corrigir estes problemas, mas até que alguém crie um pull request, não será possível extrair quaisquer dados destes sites.

Cloudflare

A Cloudflare oferece um serviço de deteção gratuito que está ativado por predefinição em todas as contas. O nosso servidor proxy personalizado será detetado em segundos e será apresentado um prompt de captcha no ecrã.

Cerca de 80% dos sites utilizam o CDN da Cloudflare. Ter os seus pedidos bloqueados pelo captcha pode significar o fim do seu scraper.

Manutenção

Embora a configuração de um proxy personalizado seja fácil, o trabalho de manutenção irá criar uma sobrecarga extremamente grande e desviar a sua atenção dos seus objetivos de negócio.

Terá de lidar com a execução das instâncias de proxy, a configuração de uma infraestrutura de auto-escalabilidade, a gestão da simultaneidade e a gestão dos clusters. A lista é interminável.

Conclusão

Agora tem um proxy web a funcionar no Heroku e uma boa compreensão de como configurá-lo, como implementá-lo e quais são as suas limitações. Se planeia utilizá-lo para um projeto de hobby, o Node Unblocker é uma boa escolha.

Mas estas desvantagens e o fraco apoio da comunidade impedem-no de o utilizar em qualquer aplicação pronta para produção.

Um serviço gerido como o WebScrapingAPI, que oferece acesso a um vasto conjunto de proxies de centros de dados, móveis e residenciais, bem como a capacidade de manipular a geolocalização, alterar cabeçalhos e criar cookies com um único parâmetro, não tem nenhuma destas limitações.

Sobre o autor
Sorin-Gabriel Marica, Desenvolvedor Full-Stack @ WebScrapingAPI
Sorin-Gabriel MaricaDesenvolvedor Full-Stack

Sorin Marica é engenheiro Full Stack e DevOps na WebScrapingAPI, onde desenvolve funcionalidades do produto e mantém a infraestrutura que garante o bom funcionamento da plataforma.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.