Como Fazer Scraping de Lojas Shopify com Proxies: Guia Completo

Saiba como raspar os dados da loja Shopify usando os endpoints da API JSON e proxies residenciais. Código Python completo e Node.js para extrair produtos, preços e dados de inventário.

Como Fazer Scraping de Lojas Shopify com Proxies: Guia Completo

Por que lojas de sucata?

Comprar poderes mais de 4 milhões de lojas on-line em todo o mundo, de pequenas marcas independentes para grandes varejistas. Isto torna-a uma das fontes mais ricas de informação sobre comércio electrónico. Ao raspar lojas Shopify, você pode rastrear os preços dos concorrentes, monitorar os lançamentos de produtos, analisar as tendências do mercado e construir bases de dados abrangentes de produtos.

A boa notícia é que o Shopify tem uma estrutura previsível que torna a raspagem mais sistemática do que a maioria das plataformas de comércio eletrônico. Cada loja do Shopify expõe certos dados através de terminais padronizados, o que significa que uma única arquitetura de raspador pode funcionar em milhares de lojas diferentes. Para uma visão mais ampla das estratégias de raspagem de comércio eletrônico, consulte Guia de raspagem de dados do comércio electrónico.

Compreendendo a estrutura da loja Shopify

Cada loja do Shopify segue o mesmo URL e padrões de dados, independentemente do tema ou personalização.

Endpoints públicos da JSON

O Shopify expõe os dados do produto através de terminais JSON que não requerem autenticação. Estas são as formas mais eficientes de raspar lojas Shopify porque você obtém dados estruturados sem processamento HTML.

Endpoints públicos da JSON
Ponto finalDados DevolvidosPaginação
/products.jsonTodos os produtos com variantes, preços, imagens?page=N&limit=250
/products/{handle}.jsonDescrição do produto únicoN/A
/collections.jsonTodas as coleções?page=N
/collections/{handle}/products.jsonProdutos numa colecção?page=N&limit=250
/meta.jsonArmazenar metadados (nome, descrição)N/A

Estrutura de dados do produto

Cada objeto de produto da API JSON inclui:

  • Informações básicas: title, handle (slug), body html (description), fornecedor, product type, tags
  • Variantes: Cada variante tem seu próprio preço, compare at price, SKU, status do inventário e valores de opção (tamanho, cor, etc.)
  • Imagens: URLs para todas as imagens de produto com texto alt
  • Datas: created at, updated at, publied at

Limitação da Taxa

Shopify aplica limites de taxa para proteger o desempenho da loja. Os endpoints públicos do JSON normalmente permitem 2-4 solicitações por segundo por IP antes de iniciar o estrangulamento. Aqui é onde proxies residenciais Tornar-se essencial — espalhar solicitações em vários IPs permite manter o rendimento sem atingir limites de taxa em nenhum único IP.

Configuração do Proxy para o Shopify

A limitação de taxa do Shopify é baseada em IP, fazendo da rotação proxy a estratégia primária para raspar em escala.

Configuração do ProxyHat

# Rotating residential proxy (new IP per request)
http://USERNAME:PASSWORD@gate.proxyhat.com:8080
# Geo-targeted for region-specific stores
http://USERNAME-country-US:PASSWORD@gate.proxyhat.com:8080
# Sticky session for paginated scraping of one store
http://USERNAME-session-shopify001:PASSWORD@gate.proxyhat.com:8080

Para raspar Shopify, use rotação por pedido ao raspar diferentes lojas e sessões pegajosas ao paginar através do catálogo de produtos de uma única loja. Este padrão imita o comportamento natural de navegação.

Implementação em Python

Aqui está um scraper Shopify pronto para produção usando O SDK Python do ProxyHatName.

Gravador de APIs JSON

import requests
import json
import time
import random
from dataclasses import dataclass, field
from typing import Optional
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
]
@dataclass
class ShopifyProduct:
    id: int
    title: str
    handle: str
    vendor: str
    product_type: str
    tags: list[str]
    variants: list[dict]
    images: list[str]
    min_price: float
    max_price: float
    created_at: str
    updated_at: str
def get_session(store_domain: str) -> requests.Session:
    """Create a session with proxy and headers configured."""
    session = requests.Session()
    session.proxies = {"http": PROXY_URL, "https": PROXY_URL}
    session.headers.update({
        "User-Agent": random.choice(USER_AGENTS),
        "Accept": "application/json",
        "Accept-Language": "en-US,en;q=0.9",
    })
    return session
def scrape_all_products(store_domain: str) -> list[ShopifyProduct]:
    """Scrape all products from a Shopify store via JSON API."""
    products = []
    page = 1
    session = get_session(store_domain)
    while True:
        url = f"https://{store_domain}/products.json?page={page}&limit=250"
        try:
            response = session.get(url, timeout=30)
            response.raise_for_status()
        except requests.RequestException as e:
            print(f"Error on page {page}: {e}")
            break
        data = response.json()
        page_products = data.get("products", [])
        if not page_products:
            break
        for p in page_products:
            prices = [float(v["price"]) for v in p.get("variants", [])
                      if v.get("price")]
            product = ShopifyProduct(
                id=p["id"],
                title=p["title"],
                handle=p["handle"],
                vendor=p.get("vendor", ""),
                product_type=p.get("product_type", ""),
                tags=p.get("tags", "").split(", ") if p.get("tags") else [],
                variants=[{
                    "id": v["id"],
                    "title": v["title"],
                    "price": v["price"],
                    "compare_at_price": v.get("compare_at_price"),
                    "sku": v.get("sku"),
                    "available": v.get("available", False),
                } for v in p.get("variants", [])],
                images=[img["src"] for img in p.get("images", [])],
                min_price=min(prices) if prices else 0,
                max_price=max(prices) if prices else 0,
                created_at=p.get("created_at", ""),
                updated_at=p.get("updated_at", ""),
            )
            products.append(product)
        print(f"Page {page}: {len(page_products)} products (total: {len(products)})")
        page += 1
        time.sleep(random.uniform(1, 3))
    return products
def scrape_collections(store_domain: str) -> list[dict]:
    """Scrape all collections from a Shopify store."""
    collections = []
    page = 1
    session = get_session(store_domain)
    while True:
        url = f"https://{store_domain}/collections.json?page={page}"
        try:
            response = session.get(url, timeout=30)
            response.raise_for_status()
        except requests.RequestException:
            break
        data = response.json()
        page_collections = data.get("collections", [])
        if not page_collections:
            break
        collections.extend(page_collections)
        page += 1
        time.sleep(random.uniform(1, 2))
    return collections
# Example: Scrape multiple Shopify stores
if __name__ == "__main__":
    stores = [
        "example-store-1.myshopify.com",
        "example-store-2.com",
        "example-store-3.com",
    ]
    for store in stores:
        print(f"\nScraping: {store}")
        products = scrape_all_products(store)
        print(f"Found {len(products)} products")
        # Save to JSON
        with open(f"{store.replace('.', '_')}_products.json", "w") as f:
            json.dump([vars(p) for p in products], f, indent=2)
        time.sleep(random.uniform(3, 7))

Monitoramento de alterações de preços nas lojas

def compare_prices(store_domain: str, previous_data: dict) -> list[dict]:
    """Compare current prices with previously stored data."""
    changes = []
    products = scrape_all_products(store_domain)
    for product in products:
        prev = previous_data.get(product.handle)
        if not prev:
            changes.append({
                "type": "new_product",
                "handle": product.handle,
                "title": product.title,
                "price": product.min_price,
            })
            continue
        if product.min_price != prev.get("min_price"):
            changes.append({
                "type": "price_change",
                "handle": product.handle,
                "title": product.title,
                "old_price": prev["min_price"],
                "new_price": product.min_price,
                "change_pct": ((product.min_price - prev["min_price"])
                               / prev["min_price"] * 100)
                              if prev["min_price"] else 0,
            })
    return changes

Implementação Node.js

Uma versão Node.js usando O Nó do ProxyHat SDK.

const axios = require("axios");
const { HttpsProxyAgent } = require("https-proxy-agent");
const fs = require("fs");
const PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080";
const agent = new HttpsProxyAgent(PROXY_URL);
async function scrapeShopifyProducts(storeDomain) {
  const products = [];
  let page = 1;
  while (true) {
    const url = `https://${storeDomain}/products.json?page=${page}&limit=250`;
    try {
      const { data } = await axios.get(url, {
        httpsAgent: agent,
        headers: {
          "User-Agent":
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
          Accept: "application/json",
        },
        timeout: 30000,
      });
      const pageProducts = data.products || [];
      if (pageProducts.length === 0) break;
      for (const p of pageProducts) {
        const prices = p.variants.map((v) => parseFloat(v.price)).filter(Boolean);
        products.push({
          id: p.id,
          title: p.title,
          handle: p.handle,
          vendor: p.vendor,
          productType: p.product_type,
          tags: p.tags ? p.tags.split(", ") : [],
          minPrice: Math.min(...prices),
          maxPrice: Math.max(...prices),
          variants: p.variants.map((v) => ({
            id: v.id,
            title: v.title,
            price: v.price,
            compareAtPrice: v.compare_at_price,
            sku: v.sku,
            available: v.available,
          })),
          images: p.images.map((img) => img.src),
          updatedAt: p.updated_at,
        });
      }
      console.log(`Page ${page}: ${pageProducts.length} products (total: ${products.length})`);
      page++;
      // Random delay 1-3 seconds
      await new Promise((r) => setTimeout(r, 1000 + Math.random() * 2000));
    } catch (err) {
      console.error(`Error on page ${page}: ${err.message}`);
      break;
    }
  }
  return products;
}
async function scrapeMultipleStores(stores) {
  const results = {};
  for (const store of stores) {
    console.log(`\nScraping: ${store}`);
    const products = await scrapeShopifyProducts(store);
    results[store] = products;
    console.log(`Found ${products.length} products`);
    // Delay between stores
    await new Promise((r) => setTimeout(r, 3000 + Math.random() * 4000));
  }
  return results;
}
// Usage
scrapeMultipleStores([
  "example-store-1.myshopify.com",
  "example-store-2.com",
]).then((results) => {
  fs.writeFileSync("shopify_data.json", JSON.stringify(results, null, 2));
  console.log("Data saved to shopify_data.json");
});

Estratégias específicas de raspagem

Descobrindo Lojas

Antes de raspar, você precisa identificar quais sites concorrentes são executados no Shopify. Os indicadores comuns incluem:

  • A /products.json endpoint retorna JSON válido
  • Código HTML contém Shopify.theme ou cdn.shopify.com
  • A x-shopify-stage cabeçalho está presente nas respostas

Manuseamento de Lojas Senha

Algumas lojas Shopify requerem uma senha para acessar. Estes são tipicamente pré-lançamento ou lojas por atacado. Os endpoints JSON retornarão um redirecionamento para a página de senha. Ignora estas lojas no teu oleoduto de raspagem, a menos que tenhas acesso autorizado.

Lidando com Domínios Personalizados

Lojas de compras costumam usar domínios personalizados em vez de .myshopify.com. A API JSON funciona da mesma forma em domínios personalizados. Basta usar o domínio voltado para o público da loja em seus pedidos.

Rastreamento de Inventário

As variantes do produto incluem available campo que indica o estado das existências. Ao rastrear esse campo ao longo do tempo, você pode monitorar os níveis de estoque do concorrente e identificar quando os produtos ficam sem estoque — informações úteis para decisões de preços e reabastecimento.

Evitando Blocos e Limites de Taxa

Embora a Shopify seja mais amiga do que a Amazon, ela ainda impõe proteções.

Evitando Blocos e Limites de Taxa
ProtecçãoDetalhesMitigação
Limitação da Taxa de IP~2-4 req/seg por IP para os terminais JSONRodar proxies residenciais através de pedidos
Proteção contra chama de nuvemAlgumas lojas usam CloudflareIPs residenciais com cabeçalhos tipo navegador
Detecção de BotsPadrões comportamentais monitoradosRandomizar atrasos e Agentes do Usuário
Páginas de SenhaPré-lançamento/lojas por grosso fechadasIgnorar ou usar o acesso autorizado

Para mais informações sobre o manuseio de sistemas anti-bots, leia nosso guia sobre como raspar sites sem ficar bloqueado.

Key takeaway: A API JSON do Shopify é a abordagem de raspagem mais eficiente, que lhe dá dados estruturados sem análise HTML. Use-o antes de voltar a raspar HTML.

Casos de Uso de Dados

Depois de coletar dados do produto Shopify, aqui estão as aplicações mais valiosas:

  • Preços competitivos: Acompanhe os preços dos concorrentes entre as categorias de produtos e ajuste sua estratégia de preços em tempo real.
  • Pesquisa de produtos: Identifique produtos de tendência, novos lançamentos e lacunas de mercado monitorando várias lojas.
  • Análise do mercado: Agregar dados em centenas de lojas Shopify para entender tendências de mercado, distribuição de preços e crescimento de categoria.
  • Enriquecimento de catálogo: Use descrições, imagens e especificações de produtos concorrentes para melhorar suas próprias listas.
  • Monitorização da marca: Acompanhe os vendedores não autorizados de seus produtos e monitore a conformidade com MAP em frentes de lojas Shopify.

Tiras de Chaves

  • Shopify /products.json endpoint é o método de raspagem mais eficiente — use-o antes da análise HTML.
  • Uma única arquitetura de raspador funciona em todas as lojas Shopify devido à estrutura padronizada.
  • Proxies residenciais com rotação superar a limitação de taxa baseada em IP do Shopify.
  • Use sessões pegajosas quando paginando através de um catálogo de uma única loja.
  • Rastreie preços de nível variante e disponibilidade para inteligência competitiva abrangente.
  • Iniciar com Proxies residenciais do ProxyHat para escalar o seu Shopify raspando de forma confiável.

Pronto para começar a raspar lojas Shopify? Explore o nosso Guia de raspagem de dados do comércio electrónico para a estratégia completa, e verificar o nosso Guia de proxy em Python e Guia proxy Node.js Para mais pormenores sobre a aplicação. Visite o nosso página de preços para começar.

Pronto para começar?

Acesse mais de 50M de IPs residenciais em mais de 148 países com filtragem por IA.

Ver preçosProxies residenciais
← Voltar ao Blog