Shopifyのproducts.jsonをスクレイピング:すべてのストアが公開するエンドポイント

HTMLの解析は忘れましょう。すべてのShopifyストアは/products.jsonでクリーンなJSONを提供します。フルカタログ、価格、バリアント、在庫情報が含まれています。ここではページネーションの制限、スピードアップのコツ、競合他社の監視に変える方法を紹介します。

eコマースをスクレイピングしたことがある人なら誰でも知っている痛み:壊れやすいCSSセレクタ、ネストされたラッパーdiv、一晩で全てを壊すレイアウトの変更。Shopifyはその解決策を提供します。Shopifyで構築されたほぼすべてのストアは、クリーンで構造化されたJSONとして全カタログを返す公開/products.jsonエンドポイントを公開しています。タイトル、ハンドル、ベンダー、タグ、バリアント、価格、在庫フラグ、画像が含まれています。HTMLの解析もヘッドレスブラウザも不要です。このガイドではエンドポイントの動作、実際のページネーション制限、大規模ストアのクロールを劇的に速くするトリック、競合の価格と在庫の監視に変える方法を説明します。

すべてのShopifyストアのエンドポイント

任意のShopifyストアのルートドメインに/products.jsonを追加すると、製品のJSONリストが取得できます。これはストアフロントが使用するのと同じデータで、Ajax APIのために意図的に公開されています。各製品には安定した数値idhandlevendorproduct_typetagsvariantsの配列(各バリアントには独自の価格、SKU、availableブール値があります)、および画像が含まれています。通常、製品ページをスクレイピングするために必要なすべてが1つのリクエストで提供されます。

import requests

url = "https://store.example.com/products.json"
r = requests.get(url, params={"limit": 250, "page": 1}, timeout=15)
products = r.json()["products"]

print(len(products), products[0]["title"])
for v in products[0]["variants"]:
    print(v["sku"], v["price"], v["available"])

最初に2つの注意点があります。Shopifyは公開エンドポイントを1ページあたり250製品に制限しています。この制限はどんなパラメータを渡しても超えることはできません。したがって、limit=1000000を設定して1回の呼び出しで全てを取得するというアドバイスは無視してください。また、少数のストアはエンドポイントを無効にしています(カスタムビルドでは時々オフにされます)。パイプラインを構築する前に有効な応答があるか確認してください。

最後までページネーション

250の制限があるため、フルカタログを取得するには空のページに達するまでページを歩く必要があります。単純なループはpageをインクリメントし、ページが空で返ってきたときに停止します。小規模なストアには正しく適しています。数百の製品を持つショップは数回のリクエストで済みます。

def all_products(base):
    page, out = 1, []
    while True:
        r = requests.get(f"{base}/products.json",
                         params={"limit": 250, "page": page}, timeout=15)
        batch = r.json()["products"]
        if not batch:
            break
        out.extend(batch)
        page += 1
    return out
Shopify products.jsonの制限を示す統計図:1ページあたり250製品の制限、バイナリサーチによる25倍速いページング、25000製品のストアで833ページ
エンドポイントは1ページあたり250製品で制限されています。スピードは大きなリクエストからではなく、最後のページを素早く見つけることから来ています。

25倍のトリック:最初に最後のページを見つける

大規模なストアでは順次ページングは遅いです。並列化できないからです。どこで止めるべきか分からないため、各ページが前のページを待ちます。解決策はバイナリサーチです。ページ番号を調べて最後の非空ページを見つけ、その後すべてのページリクエストを同時に発行します。25,000製品を833ページにわたって持つストアに対する公開ベンチマークでは、クロール時間が約120秒から最初の実行で約12秒、最後のページ番号がキャッシュされた後は約5秒に短縮されました。25倍のスピードアップです。並列リクエストの急増がスロットリングを引き起こさないように、プローブを回転するIPを通してルーティングします。

PROXY = "http://USER:PASS@gate.quantumproxies.io:8000"
proxies = {"http": PROXY, "https": PROXY}

def last_page(base, hi=1000):
    lo, last = 1, 1
    while lo <= hi:
        mid = (lo + hi) // 2
        r = requests.get(f"{base}/products.json",
                         params={"limit": 250, "page": mid},
                         proxies=proxies, timeout=15)
        if r.json()["products"]:
            last, lo = mid, mid + 1   # go higher
        else:
            hi = mid - 1              # go lower
    return last
# then request pages 1..last_page concurrently

Rob Pikeが言ったように、nが小さいときには複雑なアルゴリズムは遅いです。200製品のストアではバイナリサーチをスキップして単にループしてください。数千のカタログでは順次ページングが遅れます。

取得範囲を絞る:コレクションと単一製品

常に全カタログが必要なわけではありません。Shopifyはコレクションレベルでも同じJSONを公開しています:/collections/&lt;handle&gt;/products.jsonはそのコレクションの製品だけを返し、同じ方法でページネーションされます。1つのカテゴリだけを追跡する場合(スニーカー、香水、特定のブランドなど)、これは効率的な方法です。そして1つの製品を調べるには、そのURLに.jsonを追加します:/products/&lt;handle&gt;.jsonはその製品の完全な記録を提供し、すべてのバリアントとその在庫フラグを含みます。特定のSKUの再入荷を厳密にポーリングするのに便利です。

2つを組み合わせることでリクエストボリュームと帯域幅を抑えます。フルエンドポイントでカタログを一度発見し、関心のあるハンドルを保存し、個々の製品やコレクションを厳密なスケジュールでポーリングします。このパターンは、何百ものストアにスケールするモニターと、変更されていないカタログを再ダウンロードしてプロキシ予算を静かに消費するモニターの違いです。

競合他社の監視に変える

本当の価値は一度限りのカタログダンプではなく、時間経過による差分です。競合他社のproducts.jsonをスケジュールに基づいてスナップショットし、バリアントidでキーを付け、実行を比較して価格の変化、新製品、再入荷を瞬時にキャッチします。availablepriceは各バリアントに存在するため、製品ページに触れることなく在庫と価格のシグナルを得ることができます。

def snapshot(base):
    rows = {}
    for p in all_products(base):
        for v in p["variants"]:
            rows[v["id"]] = {
                "product": p["title"],
                "sku": v["sku"],
                "price": v["price"],
                "available": v["available"],
            }
    return rows

# diff today's snapshot against yesterday's to flag price + stock moves
def changes(old, new):
    for vid, cur in new.items():
        prev = old.get(vid)
        if prev and (prev["price"] != cur["price"] or prev["available"] != cur["available"]):
            yield cur["sku"], prev, cur

これは競合価格監視ドロップシッピングリサーチの基盤です。どちらも多くのストアで同時にスナップショットと差分のパターンを活用しています。

Shopifyスクレイピング用の高速データセンタープロキシを取得

Shopify products.jsonパイプラインのフローダイアグラム:エンドポイントから回転プロキシゲートウェイ、バリアントJSON解析、モニタリング用のスナップショット差分
スケジュールに基づいてスナップショットを取得し、バリアントを差分化すれば、追跡するすべてのストアでライブの価格と再入荷アラートを得ることができます。

実際に必要なプロキシ

products.jsonエンドポイントは公開JSONであり、強化されたチェックアウトフローではないため、寛容です。しかし、何百ものストアをスクレイピングしたり、スケジュールに基づいて1つのストアを叩いたりすると、IPごとのレート制限に達します。経済的な答えは、回転を伴う高速なデータセンタープロキシです。安価で迅速で、IPごとにリクエストを分散させるのに十分です。データセンターレンジを完全にブロックするストアには、住宅IPを予約してください。products.jsonを無効にし、レンダリングされたページやボット保護の背後にカタログを隠しているストアには、レンダリングと回転を行うScraper APIがクリーンなフォールバックです。データセンタープロキシを使用するタイミングに関するガイドでその決定をカバーしています。

よくある質問

Shopifyストアからすべての製品をJSONで取得するにはどうすればよいですか?

ストアのドメインで/products.jsonをリクエストし、?limit=250&page=Nを指定してpageをインクリメントし、ページが空の製品配列を返すまで続けます。各応答には最大250製品とそのバリアント、価格、SKU、在庫フラグが含まれています。大規模なカタログでは、最後のページをバイナリサーチで見つけ、ページを並行して取得します。

Shopify products.jsonの制限は何ですか?

公開エンドポイントは1ページあたり250製品で制限されています。limitが受け入れる最大値です。より大きな数を渡しても多くは返されません。カタログをページングする必要があります。これはShopifyの厳しい制限であり、1回のリクエストですべてを取得しようとするのではなく、ページネーションを計画してください。

Shopify products.jsonをスクレイピングすることは合法ですか?

エンドポイントはログインなしで公開されている製品データを提供しており、米国の裁判所は一般的に公開データのスクレイピングを支持しています。とはいえ、ストアの利用規約を尊重し、個人データを避け、サーバーに過負荷をかけないようにしてください。これは一般的な情報であり、法的アドバイスではありません。使用ケースと管轄区域の具体的な状況を確認してください。

products.jsonが404または空の応答を返すのはなぜですか?

ストアがShopifyにないか、商人がカスタムビルドでエンドポイントを無効にしているかのどちらかです。一部のストアは1つのIPからの繰り返しリクエストをスロットリングすることもあり、エラーのように見えることがあります。ストアがShopifyであることを確認し、IPを回転させ、リクエスト間に遅延を追加してから、エンドポイントがなくなったと仮定してください。

products.jsonエンドポイントは、Shopifyのスクレイピングをセレクタ調整の手間からクリーンなJSON取得に変えます。フルカタログ、価格、在庫が1つのURLで、1ページあたり250、バイナリサーチで高速にクロールし、競合他社の監視に簡単に差分化できます。一度発見し、重要なコレクションと製品をポーリングし、回転するデータセンターIPにリクエストを分散させれば、1回もブロックされることなく何百ものストアをスケジュールに基づいて追跡できます。HTMLパーサーもヘッドレスブラウザも、壊れやすいセレクタも必要ありません。

QuantumProxiesでShopifyのスクレイピングを始めましょう