Use Cases

Coleta de dados de pesquisa de mercado com tratamento CAPTCHA

Quantos CAPTCHAs uma coleta de pesquisa de mercado encontra pela frente? Entre 20% e 40% das páginas de fontes típicas — sites de avaliação, vagas, diretórios e bases de patentes — usam reCAPTCHA, Turnstile ou CAPTCHA de imagem para conter bots, e cada desafio sem tratamento automatizado trava o pipeline até alguém resolver manualmente. Este guia mostra como montar em Python um coletor que detecta o tipo de desafio e resolve via API da CaptchaAI, sem intervenção manual e sem reescrever o scraper toda vez que uma fonte muda de proteção.

Na prática: cerca de 30% das páginas de pesquisa de mercado acionam algum CAPTCHA. Em 1.000 páginas/dia, isso representa por volta de 300 resoluções — custo total estimado entre US$ 0,5 e US$ 3, tranquilamente dentro do plano BASIC (US$ 15/mês, 5 threads).

Onde a pesquisa de mercado esbarra em CAPTCHA

Tipo de fonte Exemplos Tipo de CAPTCHA
Sites de avaliação G2, Trustpilot, Yelp reCAPTCHA v2/v3
Quadros de vagas LinkedIn, Indeed Cloudflare Challenge
Diretórios de empresas Páginas Amarelas, Crunchbase Cloudflare Turnstile, reCAPTCHA
Redes sociais Twitter/X, Reddit Vários tipos
Bases de patentes USPTO, Google Patents reCAPTCHA v2
Dados governamentais Arquivos da SEC, censo CAPTCHA de imagem

A coluna da direita já indica o parâmetro que o coletor precisa enviar: reCAPTCHA usa googlekey e pageurl; Turnstile usa sitekey. É essa detecção por regex que o pipeline abaixo automatiza, sem precisar mapear manualmente cada fonte antes de rodar a coleta.

Um pipeline em Python que resolve CAPTCHA automaticamente

O coletor abaixo faz três coisas: busca a página, detecta se apareceu reCAPTCHA ou Turnstile e, se apareceu, resolve com a CaptchaAI antes de reenviar a requisição.

import requests
import time
import re
import csv
import os

API_KEY = os.environ["CAPTCHAAI_API_KEY"]


def solve_captcha(params):
    params["key"] = API_KEY
    resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
    if not resp.text.startswith("OK|"):
        raise Exception(f"Submit: {resp.text}")

    task_id = resp.text.split("|")[1]
    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id,
        })
        if result.text == "CAPCHA_NOT_READY":
            continue
        if result.text.startswith("OK|"):
            return result.text.split("|", 1)[1]
        raise Exception(f"Solve: {result.text}")
    raise TimeoutError()


class MarketResearchCollector:
    def __init__(self):
        self.session = requests.Session()
        self.session.headers["User-Agent"] = (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/120.0.0.0"
        )

    def fetch(self, url):
        """Fetch a page, solving CAPTCHAs as needed."""
        resp = self.session.get(url)

        # Detect reCAPTCHA
        match = re.search(
            r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', resp.text
        )
        if match:
            token = solve_captcha({
                "method": "userrecaptcha",
                "googlekey": match.group(1),
                "pageurl": url,
            })
            resp = self.session.post(url, data={
                "g-recaptcha-response": token,
            })

        # Detect Turnstile
        match = re.search(
            r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', resp.text
        )
        if match and "cf-turnstile" in resp.text:
            token = solve_captcha({
                "method": "turnstile",
                "sitekey": match.group(1),
                "pageurl": url,
            })
            resp = self.session.post(url, data={
                "cf-turnstile-response": token,
            })

        return resp.text

    def collect_reviews(self, urls):
        """Collect review data from multiple pages."""
        reviews = []
        for url in urls:
            try:
                html = self.fetch(url)
                page_reviews = self._parse_reviews(html)
                reviews.extend(page_reviews)
                print(f"  Collected {len(page_reviews)} reviews from {url}")
                time.sleep(2)  # Polite delay
            except Exception as e:
                print(f"  Error on {url}: {e}")
        return reviews

    def collect_company_profiles(self, urls):
        """Collect company profile data."""
        profiles = []
        for url in urls:
            try:
                html = self.fetch(url)
                profile = self._parse_profile(html)
                if profile:
                    profiles.append(profile)
                    print(f"  Collected: {profile.get('name', 'Unknown')}")
                time.sleep(2)
            except Exception as e:
                print(f"  Error on {url}: {e}")
        return profiles

    def _parse_reviews(self, html):
        """Extract review data from HTML."""
        reviews = []
        # Generic review extraction patterns
        for match in re.finditer(
            r'class="review-text"[^>]*>(.*?)</div>', html, re.DOTALL
        ):
            reviews.append({
                "text": match.group(1).strip()[:500],
            })
        return reviews

    def _parse_profile(self, html):
        """Extract company profile from HTML."""
        name = re.search(r'<h1[^>]*>(.*?)</h1>', html)
        desc = re.search(
            r'class="description"[^>]*>(.*?)</div>', html, re.DOTALL
        )
        return {
            "name": name.group(1).strip() if name else None,
            "description": desc.group(1).strip()[:300] if desc else None,
        }

    def export_csv(self, data, filename):
        """Export collected data to CSV."""
        if not data:
            return
        keys = data[0].keys()
        with open(filename, "w", newline="", encoding="utf-8") as f:
            writer = csv.DictWriter(f, fieldnames=keys)
            writer.writeheader()
            writer.writerows(data)
        print(f"Exported {len(data)} records to {filename}")

Como usar o coletor

collector = MarketResearchCollector()

# Collect competitor reviews
review_urls = [
    "https://example-reviews.com/product/competitor-a",
    "https://example-reviews.com/product/competitor-b",
    "https://example-reviews.com/product/competitor-c",
]
reviews = collector.collect_reviews(review_urls)
collector.export_csv(reviews, "competitor_reviews.csv")

# Collect company profiles
profile_urls = [
    "https://example-directory.com/company/alpha-corp",
    "https://example-directory.com/company/beta-inc",
]
profiles = collector.collect_company_profiles(profile_urls)
collector.export_csv(profiles, "company_profiles.csv")

Casos de uso para pesquisa de mercado com CaptchaAI

  • Monitoramento de preços da concorrência — acompanhe preços, promoções e estoque de concorrentes em marketplaces e e-commerces, com histórico suficiente para enxergar padrão sazonal.
  • Sentimento de marca em avaliações — colete avaliações de plataformas como G2 ou Trustpilot e cruze o sentimento entre várias fontes para achar onde a marca perde pontos.
  • Tendências do mercado de trabalho — extraia vagas publicadas para medir demanda por habilidades, faixas salariais praticadas e ritmo de contratação no seu setor.
  • Panorama de patentes — reúna registros de bases públicas de patentes para acompanhar tendências de inovação e o P&D dos concorrentes ao longo do tempo.
  • Monitoramento de redes sociais — acompanhe menções à marca e aos concorrentes no Twitter/X e no Reddit para captar sinais de reputação antes que virem crise.

Boas práticas para escalar a coleta

Antes de rodar isso em produção, ajuste estes cinco pontos:

  1. Espaçamento entre requisições: 2 a 5 segundos entre páginas — evita picos de tráfego que chamam atenção do WAF.
  2. Coletores simultâneos: 5 a 10 para escala moderada, subindo aos poucos conforme a fonte responder bem.
  3. Rotação de proxy: necessária acima de 100 páginas/hora, para não concentrar todo o volume em um único IP.
  4. Deduplicação de dados: gere um hash do conteúdo antes de gravar, para não reprocessar CAPTCHA em páginas já coletadas.
  5. Agendamento: rode diariamente ou semanalmente para captar tendências sem sobrecarregar as fontes em horário de pico.

Rodando a coleta a partir do Brasil

Se o time de BI está no Brasil mas as fontes ficam nos EUA ou na Europa, hospedar os workers perto do time — por exemplo em sa-east-1, São Paulo — reduz a latência do pipeline interno (fila, banco de dados, dashboards), mas não muda o RTT até o site de origem. Na prática, o tempo de resolução do CAPTCHA em si pesa menos no total do que essa latência de rede transatlântica, então não vale a pena otimizar o solver antes de otimizar a proximidade da infraestrutura da fonte. Veja também nosso guia de scraping sem bloqueio.

Perguntas frequentes sobre coleta de dados com CAPTCHA

Coletar dados públicos para pesquisa de mercado é permitido?

Na maioria dos casos, sim — dados públicos e não pessoais costumam ser aceitos. Confira sempre os termos de uso do site-fonte e evite salvar dados pessoais (nomes, e-mails, telefones) sem base legal na LGPD, ou na RGPD se a fonte estiver na Europa. Quando existir API oficial da fonte, prefira usá-la em vez do scraper — é mais estável e reduz o risco de bloqueio.

Preciso de proxy pago para rodar essa coleta em volume?

Acima de 100 páginas/hora, sim — combine rotação de proxy com o intervalo de 2 a 5 segundos entre páginas das boas práticas acima. Abaixo disso, muitas fontes toleram um único IP com espaçamento razoável, mas monitore a taxa de erro para saber quando migrar.

Quanto tempo leva para colocar esse pipeline no ar?

Com a chave de API em mãos, o esqueleto deste guia roda em poucas horas — o trabalho maior é mapear os seletores de cada site-fonte, não a parte de CAPTCHA, que já vem pronta no código acima.

É verdade que o CaptchaAI não resolve hCaptcha?

Sim, é verdade — nem o FunCaptcha (Arkose Labs) é suportado hoje. Para fontes com esses dois tipos, planeje uma alternativa: API oficial da fonte ou parceria de dados, em vez de tentar automatizar o desafio.

Como evito coletar registros duplicados na coleta diária?

Gere um hash (ex.: SHA-256) do conteúdo de cada registro e compare com o que já foi salvo antes de gravar. Isso evita reprocessar CAPTCHA em páginas que a coleta já visitou no dia anterior.

Guias relacionados

Os comentários estão desativados para este artigo.