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.
| Ponto final | Dados Devolvidos | Paginação |
|---|---|---|
/products.json | Todos os produtos com variantes, preços, imagens | ?page=N&limit=250 |
/products/{handle}.json | Descrição do produto único | N/A |
/collections.json | Todas as coleções | ?page=N |
/collections/{handle}/products.json | Produtos numa colecção | ?page=N&limit=250 |
/meta.json | Armazenar 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:8080Para 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 changesImplementaçã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.jsonendpoint retorna JSON válido - Código HTML contém
Shopify.themeoucdn.shopify.com - A
x-shopify-stagecabeç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.
| Protecção | Detalhes | Mitigação |
|---|---|---|
| Limitação da Taxa de IP | ~2-4 req/seg por IP para os terminais JSON | Rodar proxies residenciais através de pedidos |
| Proteção contra chama de nuvem | Algumas lojas usam Cloudflare | IPs residenciais com cabeçalhos tipo navegador |
| Detecção de Bots | Padrões comportamentais monitorados | Randomizar atrasos e Agentes do Usuário |
| Páginas de Senha | Pré-lançamento/lojas por grosso fechadas | Ignorar 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.jsonendpoint é 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.






