Come Scrape Shopify Stores con Proxies: Guida completa

Scopri come raschiare i dati del negozio utilizzando gli endpoint JSON API e i proxy residenziali. Codice completo Python e Node.js per l'estrazione di prodotti, prezzi e dati di inventario.

Come Scrape Shopify Stores con Proxies: Guida completa

Perché Scrape Shopify Stores?

Acquisti poteri oltre 4 milioni di negozi online in tutto il mondo, da piccoli marchi indipendenti ai principali rivenditori. Questo lo rende una delle fonti più ricche di intelligenza e-commerce. Raschiando negozi Shopify, è possibile monitorare i prezzi dei concorrenti, monitorare i lanci dei prodotti, analizzare le tendenze del mercato e costruire database di prodotti completi.

La buona notizia è che Shopify ha una struttura prevedibile che rende la demolizione più sistematica della maggior parte delle piattaforme di e-commerce. Ogni negozio Shopify espone alcuni dati attraverso endpoint standardizzati, il che significa che un'architettura single scraper può funzionare in migliaia di negozi diversi. Per una visione più ampia delle strategie di raschiamento e-commerce, vedere il nostro e-commerce dati scraping guida.

Comprendere la struttura del negozio

Ogni negozio Shopify segue lo stesso URL e i modelli di dati, indipendentemente dal tema o dalla personalizzazione.

Pubblica JSON Endpoints

Shopify espone i dati dei prodotti tramite endpoint JSON che non richiedono l'autenticazione. Questi sono il modo più efficiente per raschiare Shopify negozi perché si ottengono dati strutturati senza parasing HTML.

FineDati resiPagina
/products.jsonTutti i prodotti con varianti, prezzi, immagini?page=N&limit=250
/products/{handle}.jsonDettagli prodotto singoloN/A
/collections.jsonTutte le collezioni?page=N
/collections/{handle}/products.jsonProdotti in una collezione?page=N&limit=250
/meta.jsonMemorizzare metadati (nome, descrizione)N/A

Struttura dei dati del prodotto

Ogni oggetto prodotto dell'API JSON include:

  • Informazioni di base: titolo, maniglia (slug), body html (descrizione), venditore, product type, tag
  • Varianti: Ogni variante ha il suo prezzo, confronti at prezzo, SKU, stato dell'inventario e valori di opzione (dimensione, colore, ecc.)
  • Immagini: URL per tutte le immagini del prodotto con testo alt
  • Date: creato at, aggiornato at, pubblicato at

Limitamento del tasso

Shopify applica limiti di velocità per proteggere le prestazioni del negozio. Gli endpoint di JSON pubblici tipicamente consentono 2-4 richieste al secondo per IP prima di effettuare il timone. Questo è dove Prossi residenziali diventare essenziale — la diffusione di richieste attraverso più IP consente di mantenere il throughput senza colpire limiti di velocità su qualsiasi singolo IP.

Configurazione proxy per Shopify

La limitazione della velocità di Shopify è basata su IP, rendendo la rotazione del proxy la strategia primaria per la raschiatura a scala.

Impostazione 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

Per Shopify scraping, utilizzare la rotazione per-richiesta quando si raschiano diversi negozi, e sessioni appiccicose durante l'impaginazione attraverso un catalogo di prodotti di un singolo negozio. Questo modello imita il comportamento di navigazione naturale.

Attuazione di Python

Ecco un raschietto Shopify prodotto ProxyHat Python SDK.

JSON API Scraper

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))

Cambiamenti di prezzo di monitoraggio

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

Node.js Attuazione

Una versione Node.js utilizzando SDK del nodo di ProxyHat.

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");
});

Shopify-Specific Scraping Strategies

Scoprire Shopify Stores

Prima di raschiare, è necessario identificare quali siti concorrenti eseguire su Shopify. Gli indicatori comuni includono:

  • The /products.json endpoint restituisce valido JSON
  • sorgente HTML contiene Shopify.theme o cdn.shopify.com
  • The x-shopify-stage intestazione è presente in risposte

Gestione di negozi con password

Alcuni negozi Shopify richiedono una password per accedere. Questi sono in genere pre-lancio o negozi all'ingrosso. Gli endpoint JSON restituiranno un reindirizzamento alla pagina della password. Salta questi negozi nel tuo canale di raschiamento a meno che non hai accesso autorizzato.

Trattare con domini personalizzati

Negozi spesso utilizzano domini personalizzati invece di .myshopify.com. L'API JSON funziona allo stesso modo su domini personalizzati. Basta usare il dominio pubblico del negozio nelle vostre richieste.

Monitoraggio dell'inventario

Le varianti del prodotto includono un available campo che indica lo stato delle azioni. Tracciando questo campo nel corso del tempo, è possibile monitorare i livelli di inventario dei concorrenti e identificare quando i prodotti escono dal magazzino — intelligenza utile per i prezzi e le decisioni di ripristino.

Evitare blocchi e limiti di velocità

Mentre Shopify è più raschietto-friendly di Amazon, ancora applica protezioni.

ProtezioneDettagliMitigazione
Limitamento della tariffa IP~2-4 req/sec per IP per gli endpoint JSONRuotare i proxy residenziali attraverso le richieste
Protezione del cloudflareAlcuni negozi utilizzano CloudflareIP residenziali con intestazioni simili a browser
Rilevazione del puntoModelli comportamentali monitoratiRandomitare ritardi e Utente-Agents
Pagine di passwordPre-lancio/mercati all'ingrosso chiusiSalta o utilizza l'accesso autorizzato

Per ulteriori informazioni sulla gestione di sistemi anti-bot, leggere la nostra guida su come raschiare i siti web senza bloccarsi.

Portachiavi: Shopify's JSON API è l'approccio più efficiente di raschiatura — ti dà dati strutturati senza parsing HTML. Usalo prima di tornare a ritagliare HTML.

Casi di utilizzo dei dati

Una volta raccolti i dati del prodotto Shopify, ecco le applicazioni più preziose:

  • Prezzi competitivi: Traccia i prezzi dei concorrenti attraverso le categorie di prodotti e regola la tua strategia di prezzi in tempo reale.
  • Ricerca prodotto: Identificare prodotti di tendenza, nuovi lanci e lacune di mercato monitorando più negozi.
  • Analisi di mercato: Aggregare i dati in centinaia di negozi Shopify per comprendere le tendenze del mercato, la distribuzione dei prezzi e la crescita della categoria.
  • Arricchimento catalogo: Utilizza le descrizioni dei prodotti concorrenti, immagini e specifiche per migliorare le tue inserzioni.
  • Monitoraggio del marchio: Traccia venditori non autorizzati dei tuoi prodotti e monitora la conformità MAP su Shopify storefronts.

Asporto chiave

  • Shopify /products.json endpoint è il metodo di demolizione più efficiente — usarlo prima di parsing HTML.
  • Un'unica architettura raschietto funziona in tutti i negozi Shopify grazie alla struttura standardizzata.
  • I proxy residenziali con rotazione superano il limite di velocità IP di Shopify.
  • Utilizzare sessioni appiccicose quando impaginare attraverso il catalogo di un singolo negozio.
  • Traccia i prezzi a livello variante e la disponibilità per l'intelligenza competitiva completa.
  • Inizia con I proxy residenziali di ProxyHat per scalare il tuo Shopify raschiando in modo affidabile.

Pronto per iniziare a raschiare negozi Shopify? Scopri la nostra e-commerce dati scraping guida per la strategia completa, e controllare la nostra Guida proxy Python e Guida proxy Node.js per dettagli di implementazione. Visita la nostra pagina dei prezzi per iniziare.

Pronto per iniziare?

Accedi a oltre 50M di IP residenziali in oltre 148 paesi con filtraggio AI.

Vedi i prezziProxy residenziali
← Torna al Blog