Executando verificação de segurança...
18

Uma Visão Geral sobre Web Scraping com Node.js

Mesmo tendo iniciado na área de Web Scraping com Python, eu preferi me aventurar no ecossistema de ferramentas que o Node.js oferece. Acabei gostando bastante, partes porque eu prefiro a sintaxe do TypeScript ao invés do Python e outras porque há ferramentas de parsing de HTML que oferecem uma API semelhante ao que temos nos navegadores para manipulação de DOM.


Introdução ao Web Scraping

Web Scraping é uma técnica de obtenção de dados disponíveis na web. Difere-se da maneira tradicional utilizando APIs pois, na maioria das vezes, simula o acesso que um usuário humano faria em um site para obter seu conteúdo e, posteriormente, transformá-lo em dados estruturados que atendam a um propósito.

Com ela, podemos obter dados como notícias de portais, informações sobre produtos de um ou vários e-commerces, dados financeiros da bolsa de valores e muito mais. Web Scraping é uma forma de transformar páginas imundas em dados estruturados que agregam valor de alguma forma.

Web Scraping, assim como muitas coisas do mundo de programação é uma forma inteligente de resolver tarefas repetitivas. Isso significa que, ao invés de ter pessoas monitorando manualmente alguma informação, você terá um script raspando essa informação quantas vezes você quiser todos os dias.


Scraper vs. Crawler

No mundo de Web Scraping, podemos chamar um script ou um algoritmo de dois nomes: Scraper e Crawler. Apesar de às vezes serem confundidos como sinônimos, possuem propósitos bem definidos e talvez um pouco distintos.

Um Crawler também é um Scraper porém, um Scraper não necessariamente é um Crawler. Isso acontece porque, enquanto um Scraper é um script que busca qualquer tipo de informação de uma página, um Crawler tem como sua única função encontrar links de paginação de forma recursiva.

Como talvez você tenha imaginado, o Google utiliza Crawlers para indexar links de sites, encontrando links novos para páginas antes desconhecidas todos os dias. Por outro lado, você pode também ter imaginado que sites como Buscapé, Zoom e outros sites de promoções utilizam Scrapers para monitorar preços de produtos dos sites de e-commerce.


Listando ferramentas

Aqui vai uma lista útil das principais bibliotecas que eu uso ou conheço para a criação de scripts que extraem dados na Web:

FerramentaPropósitoNome do PacoteDescriçãoLink
AxiosCliente HTTPaxiosBiblioteca leve para fazer requisições HTTP com suporte a Promises; ideal para baixar páginas e APIs.https://npmjs.org/package/axios
Node HTML ParserParser de HTMLnode-html-parserExtrator de HTML rápido e leve, sem emular DOM completo; bom para scraping simples.https://npmjs.org/package/node-html-parser
CheerioParser de HTMLcheerioImplementa uma versão do jQuery para Node, permitindo query e manipulação de HTML facilmente.https://www.npmjs.com/package/cheerio
HeEncoder e Decorder de HTMLheConverte entidades HTML para texto puro e vice-versa; útil para limpar conteúdos codificados.https://npmjs.com/package/he
Sanetize HTMLHigienizar HTMLsanitize-htmlRemove tags e atributos perigosos de HTML, mantendo apenas o permitido.https://npmjs.com/package/sanitize-html
Markdown ItTransformador de Markdown para HTMLmarkdown-itConverte markdown em HTML com alta customização e suporte a plugins.https://npmjs.com/package/markdown-it
JMESPathQuery de JSONjmespathLinguagem declarativa para transformar e projetar dados JSON, permitindo selecionar e reestruturar objetos com expressões funcionais.https://npmjs.com/package/jamespath
JSONPathQuery de JSONjsonpathPermite navegar e filtrar estruturas JSON com sintaxe similar a XPath.https://npmjs.com/package/jsonpath
GotCliente HTTPgotCliente HTTP moderno com suporte nativo a streams, retries e HTTP2.https://npmjs.org/package/got
Got ScrapingCliente HTTPgot-scrapingVersão do Got otimizada para scraping com spoofing de headers e manipulação anti-bloqueio.https://npmjs.org/package/got-scraping
ImpitCliente HTTPimpit"Substituto do Got Scraping"; Requisições HTTP minimalistas com suporte embutido a headless scraping.https://npmjs.org/package/impit
Fake User AgentGerador de User-Agentsfake-useragentFornece rotação de User-Agents reais para evitar bloqueios em requisições.https://npmjs.com/package/fake-useragent
Header GeneratorGerador de Cabeçalhos de Requisiçãoheader-generatorGera cabeçalhos HTTP realistas com base em padrões de navegadores reais.https://npmjs.org/package/header-generator
PuppeteerManipulador de NavegadorpuppeteerControla o Chrome/Chromium de forma automatizada; ideal para páginas com JavaScript.https://npmjs.org/package/puppeteer
Puppeteer ExtraManipulador de Navegadorpuppeteer-extraWrapper do Puppeteer com suporte a plugins como stealth e adblock.https://npmjs.org/package/puppeteer-extra
Puppeteer Real BrowserManipulador de Navegadorpuppeteer-real-browserEmula um navegador real com comportamento humano para evitar detecção.https://npmjs.org/package/puppeteer-real-browser
PlaywrightManipulador de NavegadorplaywrightAutomação de navegadores com suporte multi-engine (Chromium, Firefox, WebKit).https://npmjs.com/package/playwright
Playwright ExtraManipulador de Naveadorplaywright-extraVersão estendida do Playwright com sistema de plugins similar ao Puppeteer Extra.https://npmjs.com/package/playwright-extra
Nut.jsAutomatizador janela@nut-tree-fork/nut-jsControla mouse e teclado a nível de sistema operacional para automação fora do navegador.https://npmjs.com/package/@nut-tree-fork/nut-js
JSAutoGuiAutomatizador de janelajsautoguiFerramenta inspirada no PyAutoGUI para automatizar cliques, teclado e captura de tela.https://npmjs.com/package/jsautogui
TesseractReconhecimento Óptico de Caracteresnode-tesseract-ocrWrapper para OCR Tesseract, permitindo extrair texto de imagens.https://npmjs.com/package/node-tesseract-ocr
Axios Cookie Jar SupportSuporte a Cookie Jaraxios-cookiejar-supportAdiciona a funcionalidade de gerenciamento de cookies (cookie jar) ao Axios, permitindo persistir cookies entre requisições.https://npmjs.com/package/axios-cookiejar-support
Tough CookieGerenciador de Cookiestough-cookieBiblioteca robusta para análise e armazenamento de cookies HTTP; geralmente usada em conjunto com outros clientes HTTP.https://npmjs.com/package/tough-cookie

Aqui vai uma lista de plugins para Puppeteer Extra, Puppeteer Real Browser e Playwright Extra que talvez você precise algum dia:

PluginNome do PacoteDescriçãoLink
Amazon Captcha@mihnea.dev/puppeteer-extra-amazon-captchaResolve automaticamente captchas da Amazon utilizando técnicas de OCR e interação simulada.https://npmjs.com/package/@mihnea.dev/puppeteer-extra-amazon-captcha
Stealthpuppeteer-extra-plugin-stealthObfusca características do navegador automatizado para evitar detecção por sites anti-bot.https://npmjs.com/package/puppeteer-extra-plugin-stealth
AdBlockerpuppeteer-extra-plugin-adblockerBloqueia anúncios e rastreadores durante a navegação para acelerar scraping e reduzir ruído visual.https://npmjs.com/package/puppeteer-extra-plugin-adblocker
reCAPTCHA Solverpuppeteer-extra-plugin-recaptchaDetecta automaticamente desafios reCAPTCHA e os resolve via serviços externos como 2Captcha.https://npmjs.com/package/puppeteer-extra-plugin-recaptcha
Anonymize UApuppeteer-extra-plugin-anonymize-uaSubstitui o User-Agent padrão do Puppeteer por versões mais realistas para reduzir detecção.https://npmjs.com/package/puppeteer-extra-plugin-anonymize-ua
Block Resourcespuppeteer-extra-plugin-block-resourcesImpede o carregamento de recursos pesados como imagens, fontes e mídia para acelerar scraping.https://npmjs.com/package/puppeteer-extra-plugin-block-resources

Para encontrar seletores de elementos, além do Dev Tools, utilizo algumas extensões no navegador:

FerramentaLink
SelectorGadgethttps://chromewebstore.google.com/detail/selectorgadget/mhjhnkcfbdhnjickkkdbjoemdmbfginb
xPath Finderhttps://chromewebstore.google.com/detail/xpath-finder/ihnknokegkbpmofmafnkoadfjkhlogph

Evitando bloqueios de requisições

Sites utilizam muitas formas para bloquear requisições consideradas suspeitas, que eles julgam que possa ser de bots e scripts.

1. User-Agents

Alguns utilizam algoritmos simples que apenas validam o User-Agent no cabeçalho da requisição, tentando deduzir se ele parece confiável.

Neste contexto, você pode utilizar bibliotecas como fake-useragent para rotacionar o seu User-Agent ou então descobrir qual é o seu User-Agent aqui e explicitamente definir no código para que seu site alvo então pense que você está acessando pelo seu navegador convencional. Se você estiver utilizando Puppeteer Extra, talvez seja melhor utilizar a extensão Anonymize UA (puppeteer-extra-plugin-block-resources) já que ela é preparada para esse caso de uso.

2. Rate Limiting

Já outros sites possuem além disso, possuem um rate limit que é um controle de quantas requisições podem ser feitas dentro de uma janela de tempo, ou seja, se você ultrapassar esse limite o servidor não vai te responder com o que você deseja e, em casos piores, irá banir seu IP por um tempo ou para sempre.

Para evitar ser bloqueado por rate limit você deve criar filas de requisições em seu código, permitindo x quantidade de requisições por janela de tempo determinada.

3. Cabeçalhos

Os cabeçalhos de requisição embora você talvez não saiba, diz muito sobre você. A falta de informações que normalmente um navegador de verdade enviaria levanta uma suspeita que pode acabar acarretando em uma punição para seu IP ou a não obtenção do conteúdo desejado.

Para evitar isso, eu particularmente gosto de entrar no site usando o navegador e abrir o Dev Tools e então copiar a requisição com o tipo node-fetch e ir testando o quanto daqueles cabeçalhos eu posso retirar sem afetar a resposta. Ok, esta não é uma forma muito elegante, e para lidar com isso melhor você pode optar por usar clientes HTTP que tentam se assemelhar a navegadores de verdade como o got-scraping e o impit.

4. Extensões, Webdiver exposto e preferências

Quando você está está fazendo web scraping com navegadores de verdade usando puppeteer ou playwright é comum que eventualmente você acabe sendo descoberto como uma automação por algum site ele e comece a exigir captchas para continuar ou punir o seu IP. Para contornar isso você pode utilizar o plugin Stealth (puppeteer-extra-plugin-stealth) do Puppeteer Extra que também é compatível com Playwright como citei anteriormente.

Há formas de se evitar isso manualmente também, se você quiser tentar, seria algo assim:

4.1 Forjando Extensões

Aqui, a nossa intenção é enganar a verificação em client-side que busca por extensões no nosso navegador:

await page.evaluateOnNewDocument(() => {
	Object.defineProperty(navigator, "plugins", {
		get: () => [1, 2, 3, 4, 5],
	})
})

4.2 Forjando Idiomas

await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, "languages", {
		get: () => ["en-US", "en"],
    })
})

4.3 Escondendo Extensões de Automação

await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, "webdriver", {
	    get: () => undefined
    })

	delete (navigator as any).__proto__.webdriver
})

4.4 Passando Checagem de Webdriver

await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, "webdriver", {
        get: () => false
   })
})

4.5 Passando Checagem do Chrome

await page.evaluateOnNewDocument(() => {
    (window as any).chrome = {
        runtime: {}
    }
})

4.6 Passando Checagem de Notificações

await page.evaluateOnNewDocument(() => {
	const originalQuery = window.navigator.permissions.query as any
	
	return window.navigator.permissions.query = (parameters) => {
		return parameters.name === "notifications" ? 
			Promise.resolve({ state: Notification.permission }) :
			originalQuery(parameters)
	}
})

5. Fingerprinting

Alguns sites que possuem algoritmos de bloqueio mais robustos e complexos que podem identificar você com fingerprinting. Estes sites vão criar um hash utilizando-se de características do seu computador e navegador como sistema operacional, resolução da tela, profundidade de cor da tela, extensões instaladas, fontes instaladas, APIs WebGL e Canvas (que podem revelar detalhes sobre a sua placa de vídeo), idiomas do navegador e configurações de fuso horário.

Ou seja, ainda que você toque de IP ou o seu User-Agent, você ainda terá a mesma identificação de hash. Para contornar esse tipo de coisa, geralmente usa-se Puppeteer Extra juntamente com o Plugin Stealth (puppeteer-extra-plugin-stealth).

6. Autenticação e Cookies

Alguns sites, requisitam de um token de acesso para conseguir acessar rotas e pode ser que exijam que este token esteja nos cookies do site. Neste caso, se você não estiver utilizando um navegador de verdade, irá precisar utilizar bibliotecas complementares, no caso do Axios você precisará de Axios Cookie Jar Support (axios-cookiejar-support) e Tough Cookie (tough-cookie) e no caso da Got você precisará apenas da Tough Cookie.

Já outros sites guardam esse token no localStorage, neste caso você teria de injetar usando um navegador real como o Puppeteer ou Playwright usando page.evaluate(() => {...}).

7. Captchas

Os captchas são um dos maiores problemas para quem quer fazer web scraping sem gastar dinheiro. Eles são criados para limpar o tráfego dos sites, bloqueando e punindo o acesso de bots.

Alguns captchas são mais fáceis de se desviar, como por exemplo o captcha da Amazon, que consiste em apenas identificar caracteres distorcidos, digitar em um campo e clicar em um botão. Você pode tentar implementar isso usando Puppeteer e Tesseract.js, mas o Puppeteer Extra já tem a solução em forma de extensão, o Amazon Captcha (@mihnea.dev/puppeteer-extra-amazon-captcha) que eu havia citado lá em cima.

Outros captchas como por exemplo o da hCaptcha, reCaptcha e Cloudflare Turnstile são mais complexos de se desviar, se você conseguir criar uma solução automatizada sem depender de um serviço de terceiros provavelmente vai parar de funcionar muito em breve. Eu consegui contornar o Cloudflare Turnstile usando uma combinação de puppeteer-real-browser para ser um navegador que aparenta ser normal e @nut-tree-fork/nut-js para dar um clique mais realista.

Se você precisar lidar com captchas desse tipo para um projeto sério, recomendo fortemente que você utilize serviços com 2Captcha, Capsolve ou NextCaptcha.


Estou escrevendo um livro :D

Galera, queria compartilhar com vocês que que eu estou escrevendo um livro sobre Web Scraping com Node.js e estava me sentindo um pouco travado, achando que a forma com que escrevo talvez não fosse o suficiente para um livro, mas continuo tentando!

E foi com o objetivo de tentar me soltar um pouco que eu fiz este artigo, espero que tenha sido útil para vocês, e se ainda não foi, espero que um dia seja.

Carregando publicação patrocinada...
8
1
-1
4

Achei muito legal tudo que vc disse. Eu gosto muito desse assunto e há uns anos atrás cheguei a fazer bastante coisa pra vasculhar feeds do instagram e gerar RSS pra posts e stories. Dava um trabalhão!

Uma dúvida, vc chegou a testar residential proxy? Ou não precisou?

2
1

Muito obrigado, meu nobre! Nunca cheguei a precisar de usar proxy não, é algo que eu tenho que estudar um pouco para colocar no livro, para compensar a falta de experiência prática

2
2

Conteúdo muito bom pra quem gosta de webscraping como eu.

Quando construí minha primeira api foi pra fazer webscraping em um site de animes e logo me deparei com os bloqueios quando subi o código para uma Vercel da vida.

Nessa minha experiência específica, eu lembro de ter utilizado esses plugins de stealth e etc, porém mesmo assim os bloqueios continuavam, daí descobri que a Vercel utiliza AWS por debaixo dos panos e que os ips deles são meio que "sujos" e reconhecidos facilmente por serviços como Cloudflare. Em outra situação tive o mesmo problema, então subi o scraper no Railway que parece ter ips bem melhores e não tive problemas.

2

Excelente tua didática, não li ainda o seu rascunho do livro, mas te sugiro que que vá colocando alguns exemplos práticos e até situações mais problemáticas mesmo como uso de captcha, sessão, etc...

2
2
  • Gostei muito que você colocou a sessão ## Evitando bloqueios de requisições Principalmente por que você vai inevitavelmente bater nesse problema se começar a ter qualquer escala... Principalmente hoje o cloudflare é bem sofisticado em deteção de bots... Teve um projeto que eu usei uma api externa (scrapingbee) porque rodar o scraper tava impossível.

  • Entre playwright e puppeteer qual o melhor, ou pelo menos quais os diferenciais?

2

Cara, para burlar a Cloudflare existem algumas coisas como Puppeteer Extra + Stealth Plugin ou Puppeteer Real Browser, chegou a testar eles na época?

Eu particularmente só uso o Puppeteer. O Playwright tem a fama de ser mais moderno, a API dele é bastante semelhante ao Puppeteer pelo o que eu vi, há compatibilidade entre os Plugins que fizeram para o Puppeteer Extra no Playwright Extra, mas nunca cheguei a testar.

2
1

Se você tiver como fazer login via API, melhor usar um Axios da vida, se precisar realmente enviar um formulário no frontend, use o Puppeteer.

Caso você encontre captchas e sistemas antibots, você vai precisar de algo mais avançado como Puppeteer Extra + Stealth Plugin (talvez plugins de resolução de captchas também) ou Puppeteer Real Browser.

Edit: E muito obrigado pelo apio!

2
1

Grande parte das ferramentas eu encontrei por acaso no GitHub, tipo por recomendações a pesquisas à toa.

Agora falando sobre conceitos, aprendi com um amigo meu (oralmente) e com a leitura de um livro que fizeram para Python: Web Scraping com Python – Coletando dados da web moderna. O meu é a edição 2, que está um pouco desatualizada, mas deu uma base excelente.

À partir daí eu fui meio que fazendo pesquisas de forma independente e projetos pessoais, enfrentando desafios e buscando soluções para eles.

4

eles crescem tão rápido!! parece que foi ontem que lhe catequizei com a palavra do webscraping, só é lamentável que você tenha se tornado um usuário de Js no backend

2

Acho muito bom também usar o Effect, não é pra scrapping, mas por causa de como ele funciona, é perfeito pra se recuperar de uma falha. Webscrapping com ele fica muito mais fácil. Usem também o Patchright. Ele tem versão pra python e node

1
3

Quando passei a usar o Effect, ficou muito mais fácil, ele é um tanto diferente, mas é rápido e depois que voce pega o jeito, fica difícil não usar, ele é muito bom mesmo.