Scraping BrowserGuiasBypass de CloudFlare na raspagem da Web

Bypass do Cloudflare em raspagem da web

Este documento técnico explica como usar as ferramentas Navegador de Raspagem Scrapeless e Desbloqueador Web Scrapeless para lidar com diversos desafios de segurança configurados pelo Cloudflare. Recursos principais incluem contornar o Desafio JS do Cloudflare, o Turnstile do Cloudflare e executar renderização JavaScript para acessar conteúdo protegido pelo Cloudflare. Este documento fornecerá conhecimento de fundo relevante, introduções de recursos, etapas operacionais e explicações de exemplos de código.

Compreendendo os Desafios e Camadas de Segurança do Cloudflare

O Cloudflare, um serviço popular de segurança e desempenho da web, protege principalmente sites de tráfego malicioso ou inesperado, como bots e scanners. Para isso, o Cloudflare implementa diversos mecanismos de detecção e defesa, incluindo, mas não se limitando a:

1. Desafio JS (Desafio JavaScript): Requer que o navegador do visitante execute código JavaScript específico para verificar se é um ambiente de navegador legítimo com funcionalidade padrão.

2. Alternativa CAPTCHA Turnstile: Um mecanismo de verificação menos intrusivo para distinguir entre usuários humanos e bots.

3. Impressão digital do navegador: Coleta e analisa características técnicas do navegador e do dispositivo (por exemplo, User-Agent, resolução da tela, fontes instaladas, plug-ins) para identificar e rastrear visitantes.

4. Limitação de taxa: Monitora e limita o número de solicitações de uma única fonte (por exemplo, endereço IP) dentro de um tempo específico para evitar força bruta ou abuso de recursos.

Essas camadas de segurança impedem que bibliotecas de solicitação HTTP básicas, scripts simples ou navegadores headless configurados incorretamente acessem sites protegidos pelo Cloudflare, resultando em falhas de verificação e negação de acesso.

Diferenças Entre o Desafio JS do Cloudflare e Outros Desafios

A singularidade do Desafio JS do Cloudflare reside em seu método de verificação. Ele não apenas exige que os usuários concluam uma tarefa interativa simples (por exemplo, reconhecimento de imagem); ele exige que o ambiente do cliente (navegador) analise e execute com sucesso o código JavaScript gerado dinamicamente, muitas vezes ofuscado, do Cloudflare. Esse código executa verificações de ambiente, tarefas computacionalmente intensivas ou outra lógica para verificar as capacidades de comportamento complexo do cliente, imitando um navegador real.

Superar o Desafio JS envolve gerar um token de liberação válido (geralmente na forma de um cookie cf_clearance). Esse token comprova que o cliente passou na verificação da capacidade de execução de JavaScript. Muitas ferramentas de automação não possuem um mecanismo de execução JavaScript completo e simulação de ambiente de navegador realista, falhando, portanto, nesses desafios.

Contornando o Desafio JS do Cloudflare Usando o Navegador de Raspagem Scrapeless

O Navegador de Raspagem Scrapeless é projetado para lidar com medidas complexas de proteção de sites, incluindo o Desafio JS do Cloudflare.

Etapas e Exemplo de Código

Configuração do Ambiente

Criar uma Pasta de Projeto

Crie uma nova pasta para o projeto, por exemplo: scrapeless-bypass.

Navegue até a pasta no seu terminal:

cd path/to/scrapeless-bypass

Inicializar o Projeto Node.js

Execute o seguinte comando para criar um arquivo package.json:

npm init -y

Instalar Dependências Necessárias

Instale o Puppeteer-core, que permite a conexão remota a instâncias do navegador:

npm install puppeteer-core

Se o Puppeteer ainda não estiver instalado no seu sistema, instale a versão completa:

npm install puppeteer puppeteer-core

Obtenha e Configure Sua Chave de API Scrapeless.

Conecte-se e Certifique-se de que o CAPTCHA Foi Resolvido com Sucesso

O Scrapeless detecta e resolve automaticamente CAPTCHAs ao conectar-se ao navegador para acessar o site de destino. No entanto, precisamos garantir que o CAPTCHA foi resolvido com sucesso. O Navegador de Raspagem Scrapeless estende o CDP (Chrome DevTools Protocol) padrão com um conjunto poderoso de capacidades personalizadas. O status do solucionador de CAPTCHA pode ser observado diretamente verificando os resultados retornados da API CDP:

  • Captcha.detected: CAPTCHA detectado
  • Captcha.solveFinished: CAPTCHA resolvido com sucesso
  • Captcha.solveFailed: Falha na resolução do CAPTCHA
import puppeteer from "puppeteer-core";
import EventEmitter from 'events';
import { Scrapeless } from '@scrapeless-ai/sdk';
 
const emitter = new EventEmitter();
 
const client = new Scrapeless({ apiKey: 'API Key' });
 
const { browserWSEndpoint } = client.browser.create({
    session_name: 'sdk_test',
    session_ttl: 180,
    proxy_country: 'ANY',
    session_recording: true,
    fingerprint,
});
 
export async function example(url) {
  const browser = await puppeteer.connect({
    browserWSEndpoint,
    defaultViewport: null
  });
  console.log("Verbonden met Scrapeless browser");
  try {
    const page = await browser.newPage();
    // Listen for captcha events
    console.debug("addCaptchaListener: Start listening for captcha events");
    await addCaptchaListener(page);
    console.log("Navigated to URL:", url);
    await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
    console.log("onCaptchaFinished: Waiting for captcha solving to finish...");
    await onCaptchaFinished()
    // Screenshot for debugging
    console.debug("Taking screenshot of the final page...");
    await page.screenshot({ path: 'screenshot.png', fullPage: true });
  } catch (error) {
    console.error(error);
  } finally {
    await browser.close();
    console.log("Browser closed");
  }
}
 
async function addCaptchaListener(page) {
  const client = await page.createCDPSession();
  client.on("Captcha.detected", (msg) => {
    console.debug("Captcha.detected: ", msg);
  });
  client.on("Captcha.solveFinished", async (msg) => {
    console.debug("Captcha.solveFinished: ", msg);
    emitter.emit("Captcha.solveFinished", msg);
    client.removeAllListeners()
  });
}
 
async function onCaptchaFinished(timeout = 60_000) {
  return Promise.race([
    new Promise((resolve) => {
      emitter.on("Captcha.solveFinished", (msg) => {
        resolve(msg);
      });
    }),
    new Promise((_, reject) => setTimeout(() => reject('Timeout'), timeout))
  ])
}

Este exemplo de fluxo de trabalho acessa o site de destino e confirma que o CAPTCHA foi resolvido com sucesso, ouvindo o evento Captcha.solveFinished do CDP. Finalmente, ele captura uma imagem do página para verificação.

Este exemplo define dois métodos principais:

  • addCaptchaListener: para ouvir eventos de CAPTCHA dentro da sessão do navegador
  • onCaptchaFinished: para esperar até que o CAPTCHA tenha sido resolvido

O código de exemplo acima pode ser usado para ouvir eventos CDP para três tipos comuns de CAPTCHA discutidos neste artigo: reCAPTCHA v2, Cloudflare Turnstile e Cloudflare 5s Challenge.

Observe que o Desafio Cloudflare 5s é um pouco especial. Às vezes, ele não aciona um desafio real, e depender apenas da detecção de eventos CDP para o sucesso pode levar a timeouts. Portanto, esperar que um elemento específico apareça na página após o desafio é uma solução mais estável.

Conectando ao WebSocket Sem Servidor do Scrapeless Browser

Scrapeless fornece uma conexão WebSocket, permitindo que o Puppeteer interaja diretamente com o navegador sem servidor, contornando os desafios do Cloudflare.

O endereço de conexão WebSocket completo:

wss://browser.scrapeless.com/browser?token=APIKey&session_ttl=180&proxy_country=ANY

Exemplo de Código: Contornando o Desafio do Cloudflare

Precisamos apenas do seguinte código para conectar ao serviço sem servidor do Scrapeless.

import puppeteer from 'puppeteer-core';
 
const API_KEY = 'your_api_key'
const host = 'wss://browser.scrapeless.com';
const query = new URLSearchParams({
  token: API_KEY,
  session_ttl: '180', // The life cycle of a browser session, in seconds
  proxy_country: 'GB', // Agent country
  proxy_session_id: 'test_session_id', // The proxy session id is used to keep the proxy ip unchanged. The session time is 3 minutes by default, based on the proxy_session_duration setting.
  proxy_session_duration: '5' // Agent session time, unit minutes
}).toString();
 
const connectionURL = `${host}/browser?${query}`;
const browser = await puppeteer.connect({
    browserWSEndpoint: connectionURL,
    defaultViewport: null,
});
console.log('Connected!')

Acessando Sites Protegidos pelo Cloudflare e Verificação de Imagem

Em seguida, usamos o scrapeless browserless para acessar diretamente o site de teste do desafio do cloudflare e adicionar uma imagem, permitindo a verificação visual. Antes de tirar a imagem, observe que você precisa usar waitForSelector para esperar pelos elementos na página, garantindo que o desafio do Cloudflare tenha sido contornado com sucesso.

const page = await browser.newPage();
await page.goto('https://www.scrapingcourse.com/cloudflare-challenge', {waitUntil: 'domcontentloaded'});
// By waiting for elements in the site page, ensuring that the Cloudflare challenge has been successfully bypassed.
await page.waitForSelector('main.page-content .challenge-info', {timeout: 30 * 1000})
await page.screenshot({path: 'challenge-bypass.png'});

Neste ponto, você contornou o desafio do Cloudflare usando o Scrapeless Browserless.

Após passar no desafio do Cloudflare, você pode recuperar os cabeçalhos da solicitação e o cookie cf_clearance da página bem-sucedida.

const cookies = await browser.cookies()
const cfClearance = cookies.find(cookie => cookie.name === 'cf_clearance')?.value

Ative a interceptação de solicitações para capturar os cabeçalhos da solicitação e corresponder às solicitações da página após o desafio do Cloudflare.

await page.setRequestInterception(true);
page.on('request', request => {
  // Match page requests after cloudflare challenge
  if (request.url().includes('https://www.scrapingcourse.com/cloudflare-challenge') && request.headers()?.['origin']) {
    const accessRequestHeaders = request.headers();
    console.log('[access_request_headers] =>', accessRequestHeaders);
  }
  request.continue();
});

Contornando o Cloudflare Turnstile Usando o Navegador de Raspagem Scrapeless

O Navegador de Raspagem Scrapeless também lida com os desafios do Cloudflare Turnstile.

Da mesma forma, ao enfrentar o Cloudflare Turnstile, o navegador de raspagem sem servidor ainda pode lidar com ele automaticamente. O exemplo a seguir acessa o site de teste do cloudflare-turnstile. Após inserir o nome de usuário e a senha, ele usa o método waitForFunction para aguardar dados de window.turnstile.getResponse(), garantindo que o desafio foi contornado com sucesso. Em seguida, ele tira uma imagem e clica no botão de login para navegar para a próxima página.

Etapas e Exemplo de Código:

const page = await browser.newPage();
await page.goto('https://www.scrapingcourse.com/login/cf-turnstile', { waitUntil: 'domcontentloaded' });
await page.locator('input[type="email"]').fill('admin@example.com')
await page.locator('input[type="password"]').fill('password')
// Wait for turnstile to unlock successfully
await page.waitForFunction(() => {
  return window.turnstile && window.turnstile.getResponse();
});
await page.screenshot({ path: 'challenge-bypass-success.png' });
await page.locator('button[type="submit"]').click()
await page.waitForNavigation()
await page.screenshot({ path: 'next-page.png' });

Após executar este script, você verá o efeito de desbloqueio por meio de imagens.

Usando o Desbloqueador Web Scrapeless para Renderização JavaScript

Para sites protegidos pelo Cloudflare em que o conteúdo principal depende da execução de JavaScript do lado do cliente para carregamento e exibição completos, o Desbloqueador Web Scrapeless fornece uma solução dedicada.

Scrapeless A API Universal habilita a renderização JavaScript e a interação dinâmica, tornando-a uma ferramenta eficaz para contornar o Cloudflare.

Renderização JavaScript

A renderização JavaScript suporta o tratamento de conteúdo carregado dinamicamente e SPAs (Single-Page Applications). Ele suporta um ambiente de navegador completo, lidando com interações de página mais complexas e requisitos de renderização.

Com js_render=true, usaremos o navegador para a solicitação

{
  "actor": "unlocker.webunlocker",
  "input": {
    "url": "https://www.google.com/",
    "js_render": true
  },
  "proxy": {
    "country": "US"
  }
}

Instruções JavaScript

Fornece um amplo conjunto de instruções JavaScript, permitindo interação dinâmica com páginas da web.

Essas instruções permitem clicar em elementos, preencher formulários, enviar formulários ou aguardar o aparecimento de elementos específicos, fornecendo flexibilidade para tarefas como clicar em um botão “Ler Mais” ou enviar um formulário.

{
  "actor": "unlocker.webunlocker",
  "input": {
    "url": "https://example.com",
    "js_render": true,
    "js_instructions": [
      {
        "wait_for": [
          ".dynamic-content",
          30000
        ]
        // Wait for element
      },
      {
        "click": [
          "#load-more",
          1000
        ]
        // Click element
      },
      {
        "fill": [
          "#search-input",
          "search term"
        ]
        // Fill form
      },
      {
        "keyboard": [
          "press",
          "Enter"
        ]
        // Simulate key press
      },
      {
        "evaluate": "window.scrollTo(0, document.body.scrollHeight)"
        // Execute custom JS
      }
    ]
  }
}

Exemplo de Bypass de Desafio

O exemplo a seguir usa o axios para enviar uma solicitação ao serviço Desbloqueador Web do Scrapeless. Ele habilita js_render e usa a instrução wait_for no parâmetro js_instructions para aguardar um elemento na página após contornar o desafio do Cloudflare:

import axios from 'axios'
 
async function sendRequest() {
  const host = "api.scrapeless.com";
  const url = `https://${host}/api/v1/unlocker/request`;
  const API_KEY = 'your_api_key'
 
  const payload = {
    actor: "unlocker.webunlocker",
    proxy: {
      country: "US"
    },
    input: {
      url: "https://www.scrapingcourse.com/cloudflare-challenge",
      js_render: true,
      js_instructions: [
        {
          wait_for: [
            "main.page-content .challenge-info",
            30000
          ]
        }
      ]
    },
  }
 
  try {
    const response = await axios.post(url, payload, {
      headers: {
        'Content-Type': 'application/json',
        'x-api-token': API_KEY
      }
    });
    console.log("[page_html_body] =>", response.data);
  } catch (error) {
    console.error('Error:', error);
  }
}
sendRequest();

Após executar o script acima, você poderá ver o HTML da página que contornou com sucesso o desafio do Cloudflare no console.