Casos de Uso

Monitoramento de estoque de varejo com manipulação de CAPTCHA

As plataformas de comércio eletrônico protegem as páginas de produtos e dados de inventário com CAPTCHAs para evitar roubos de concorrentes e compras de bots. CaptchaAI permite monitoramento automatizado de estoque, rastreamento de preços e alertas de disponibilidade.


CAPTCHAs em plataformas de comércio eletrônico

Plataforma Tipo CAPTCHA Gatilho Dados
Amazônia reCAPTCHA v2 Acesso de alto volume Preço, estoque, comentários
Wal-Mart reCAPTCHA v3 + Cloudflare Detecção de bots Estoque, preços
mais adequado compra reCAPTCHA v2 Verificação de adicionar ao carrinho Estoque, preços
Alvo Cloudflare Turnstile Acesso automatizado Disponibilidade
Lojas Shopify Cloudflare Turnstile Limitação de taxa Dados do produto
eBay reCAPTCHA v2 Pesquisa + acesso à listagem Listagens, preços

Monitor de produto

import requests
import time
import re
import json
from datetime import datetime
from bs4 import BeautifulSoup

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def solve_captcha(method, sitekey, pageurl, **kwargs):
    data = {
        "key": CAPTCHAAI_KEY, "method": method,
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    }
    data.update(kwargs)
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        r = result.json()
        if r["request"] != "CAPCHA_NOT_READY":
            return r["request"]
    raise TimeoutError("Timeout")


class RetailMonitor:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
            "Accept": "text/html,application/xhtml+xml,*/*;q=0.8",
            "Accept-Language": "en-US,en;q=0.9",
        })

    def check_product(self, url):
        """Check single product's price and availability."""
        resp = self.session.get(url, timeout=30)

        # Handle CAPTCHA
        if self._has_captcha(resp.text):
            resp = self._solve_and_retry(resp.text, url)

        soup = BeautifulSoup(resp.text, "html.parser")
        return {
            "url": url,
            "title": self._text(soup, "h1, .product-title, #productTitle"),
            "price": self._text(soup, ".price, .a-price .a-offscreen, .prod-price"),
            "availability": self._text(soup, "#availability, .stock-status, .fulfillment"),
            "in_stock": self._check_stock(soup),
            "timestamp": datetime.now().isoformat(),
        }

    def monitor_products(self, product_urls, interval_sec=1800):
        """Continuously monitor products for changes."""
        history = {}

        while True:
            for url in product_urls:
                try:
                    current = self.check_product(url)

                    # Check for changes
                    prev = history.get(url)
                    if prev:
                        changes = self._detect_changes(prev, current)
                        if changes:
                            self._alert(current["title"], changes)

                    history[url] = current
                    time.sleep(3)

                except Exception as e:
                    print(f"Error checking {url}: {e}")

            print(f"Cycle complete: {len(product_urls)} products checked")
            time.sleep(interval_sec)

    def track_prices(self, product_urls, output_file="prices.json"):
        """Single price check across all products."""
        results = []
        for url in product_urls:
            try:
                data = self.check_product(url)
                results.append(data)
                time.sleep(3)
            except Exception as e:
                results.append({"url": url, "error": str(e)})

        with open(output_file, "w") as f:
            json.dump(results, f, indent=2)
        print(f"Tracked {len(results)} products → {output_file}")
        return results

    def _has_captcha(self, html):
        return any(tag in html.lower() for tag in [
            'data-sitekey', 'g-recaptcha', 'cf-turnstile', 'captcha',
        ])

    def _solve_and_retry(self, html, url):
        match = re.search(r'data-sitekey="([^"]+)"', html)
        if not match:
            return self.session.get(url)

        sitekey = match.group(1)
        if 'cf-turnstile' in html:
            token = solve_captcha("turnstile", sitekey, url)
            return self.session.post(url, data={"cf-turnstile-response": token})
        else:
            token = solve_captcha("userrecaptcha", sitekey, url)
            return self.session.post(url, data={"g-recaptcha-response": token})

    def _text(self, soup, selector):
        el = soup.select_one(selector)
        return el.get_text(strip=True) if el else ""

    def _check_stock(self, soup):
        stock_el = soup.select_one("#availability, .stock-status")
        if stock_el:
            text = stock_el.get_text(strip=True).lower()
            return "in stock" in text or "available" in text
        return None

    def _detect_changes(self, prev, current):
        changes = []
        if prev["price"] != current["price"]:
            changes.append(f"Price: {prev['price']} → {current['price']}")
        if prev["in_stock"] != current["in_stock"]:
            status = "In Stock" if current["in_stock"] else "Out of Stock"
            changes.append(f"Stock: → {status}")
        return changes

    def _alert(self, title, changes):
        print(f"ALERT [{title}]: {', '.join(changes)}")


# Usage
monitor = RetailMonitor(
    proxy="http://user:pass@residential.proxy.com:5000"
)

products = [
    "https://store.example.com/product/abc123",
    "https://store.example.com/product/def456",
    "https://store.example.com/product/ghi789",
]

# One-time price check
results = monitor.track_prices(products)

# Or continuous monitoring (every 30 min)
# monitor.monitor_products(products, interval_sec=1800)

Digitalização de estoque em toda a categoria

def scan_category(base_url, category, max_pages=20):
    """Scan an entire product category for stock status."""
    monitor = RetailMonitor(
        proxy="http://user:pass@residential.proxy.com:5000"
    )

    all_products = []
    for page in range(1, max_pages + 1):
        url = f"{base_url}/{category}?page={page}"
        resp = monitor.session.get(url, timeout=30)

        if monitor._has_captcha(resp.text):
            resp = monitor._solve_and_retry(resp.text, url)

        soup = BeautifulSoup(resp.text, "html.parser")
        items = soup.select(".product-card, .s-result-item")

        if not items:
            break

        for item in items:
            all_products.append({
                "name": monitor._text(item, ".product-name, .a-text-normal"),
                "price": monitor._text(item, ".price, .a-price"),
                "stock": monitor._text(item, ".stock, .a-color-success"),
                "url": item.select_one("a")["href"] if item.select_one("a") else "",
            })

        time.sleep(3)

    return all_products

Comparação de preços do concorrente

def compare_product_across_stores(product_name, stores):
    """Compare prices across retailers for the same product."""
    results = []

    for store in stores:
        monitor = RetailMonitor(proxy=store.get("proxy"))
        search_url = f"{store['base_url']}/search?q={product_name}"

        try:
            resp = monitor.session.get(search_url, timeout=30)
            if monitor._has_captcha(resp.text):
                resp = monitor._solve_and_retry(resp.text, search_url)

            soup = BeautifulSoup(resp.text, "html.parser")
            first_result = soup.select_one(".product-card, .s-result-item")

            if first_result:
                results.append({
                    "store": store["name"],
                    "price": monitor._text(first_result, ".price"),
                    "in_stock": "in stock" in first_result.get_text().lower(),
                })
        except Exception as e:
            results.append({"store": store["name"], "error": str(e)})

        time.sleep(5)

    results.sort(key=lambda x: x.get("price", "zzzz"))
    return results

Cronograma de monitoramento

Tipo de produto Verifique a frequência Tipo de proxy
Eletrônica A cada 30 minutos Residencial rotativo
Mercearia A cada 4 horas Residencial rotativo
Moda A cada 2 horas Residencial
Lançamentos limitados A cada 1 minuto rede mobile autorizada
Bens domésticos A cada 6 horas Residencial
Mercadorias A cada 12 horas Datacenter (geralmente suficiente)

Solução de problemas

Problema Causa Correção
CAPTCHA em todas as páginas do produto IP sinalizado ou taxa excedida Aumente o atraso, gire os proxies
Preço incorreto raspado Preços dinâmicos renderizados por JS Use Selenium/Puppeteer em vez disso
Página "Verificação do robô" Detecção de bot no estilo Amazon Use cabeçalhos realistas + egress de rede autorizado
O estoque mostra "indisponível" Disponibilidade com restrição geográfica Combine o proxy com a região de destino
Dados do produto ausentes Estrutura da página alterada Atualizar seletores CSS

Perguntas frequentes

Com que frequência posso verificar as páginas dos produtos?

Cada 30-60 minutos por produto é seguro para a maioria dos varejistas. O monitoramento de frequência mais alta (1-5 min) funciona, mas requer mais proxies e aciona CAPTCHAs.

Devo usar sessões rotativas ou fixas?

Rotação - cada página de produto é uma solicitação independente. Sessões fixas só são necessárias se a verificação dos detalhes do produto exigir navegação.

Posso monitorar milhares de produtos?

Sim. Distribua solicitações entre vários IPs de proxy e escalone verificações. Em 1.000 produtos com atrasos de 3 segundos, um ciclo completo leva aproximadamente 50 minutos.


Guias Relacionados

  • Proxies residenciais rotativos
  • Sessões fixas vs rotativas
  • Monitoramento da Cadeia de Suprimentos

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