Best Buyの価格と在庫をスクレイピングする方法 2026 — API vs HTMLのトレードオフ
Best Buyのリアルタイム価格と店舗在庫を取得する場合、最初の選択は公式Products APIとHTMLスクレイピングのどちらを使うかです。Best Buyは公式Developer APIを提供していますが、このAPIは承認制であり、APIキーの発行には審査プロセスが必要です。また、APIのレート制限は比較的厳しく、リアルタイムの価格変動や店舗レベルの在庫状況はAPIだけでは完全に追跡できません。
そのため、実稼働のBest Buy価格トラッカーやBest Buy在庫チェッカーの多くは、Webサイトから直接データを抽出するHTMLスクレイピングに頼っています。本記事では、ProxyHatの住宅プロキシを活用してBest Buyの価格と在庫をスクレイピングする実践的な方法を、コード例と具体的なセレクタとともに解説します。
Best Buyのアンチボットスタック — Akamai Bot Manager
Best BuyはAkamai Bot Managerを使用して自動化トラフィックを検出・ブロックしています。Akamaiの仕組みを理解することは、スクレイピングを成功させる上で不可欠です。
Akamaiの検出メカニズム
Akamai Bot Managerは主に2つのCookieを使用してボットを検出します:
- _abck — ブラウザのフィンガープリント、TLSジェスチャー、JavaScript実行環境のセンサーデータを含むCookie
- bm_sz — セッションごとのボットスコアを記録するCookie
データセンターIPからのリクエストは、通常約3〜5回のリクエスト以内にAkamaiのチャレンジをトリガーします。これは、AkamaiがIPレピュテーション、TLSフィンガープリント、リクエストパターンの異常を組み合わせて判定するためです。一度チャレンジが発生すると、403ステータスコードまたはJavaScriptチャレンジページが返されます。
データセンターIPでBest Buyをスクレイピングしても、最初の数リクエストでブロックされるのが通常の挙動です。住宅プロキシの使用は必須要件と考えてください。
curl_cffiによるTLS偽装の重要性
標準のPython requestsライブラリは、TLSハンドシェイクの段階でPythonのフィンガープリントを露出します。Akamaiはこのフィンガープリントを検出してボットと判定します。curl_cffiライブラリは、ChromeやFirefoxのTLSフィンガープリントを模倣するため、AkamaiのTLSベースの検出を回避するのに有効です。
URLパターンとセレクタ
Best Buyのスクレイピングで押さえるべき主要なURLパターンとCSSセレクタを整理します。
商品ページ(SKUページ)
商品ページのURLパターンは以下の形式です:
https://www.bestbuy.com/site/-/<sku>.p?skuId=<sku>例えばSKU 6523293の商品ページは:
https://www.bestbuy.com/site/-/6523293.p?skuId=6523293主要なCSSセレクタ:
| データ | CSSセレクタ | 備考 |
|---|---|---|
| 商品タイトル | .sku-title h1 | ページ上部のタイトル |
| 現在価格 | .priceView-customer-price span | セール価格 |
| 定価 | .priceView-price-navigation-price span | 割引前価格 |
| 在庫状況 | .fulfillment-fulfillment-summary | 配送・店舗在庫の概要 |
| SKU番号 | .sku-model .sku-value | ページ下部 |
内部JSONエンドポイント
Best Buyのサイトは、ページ読み込み後に内部APIを呼び出して価格と在庫データを取得します。これらのエンドポイントはSKU IDと郵便番号をパラメータとして受け取ります:
# 価格・在庫JSONエンドポイント
https://www.bestbuy.com/productfulfillment?skus=<sku>&zip=<zipcode>このエンドポイントは、指定した郵便番号周辺の店舗在庫情報をJSON形式で返します。レスポンスの構造(一部省略):
{
"sku": "6523293",
"price": 199.99,
"inStoreAvailability": true,
"stores": [
{"storeId": "123", "stock": 3, "distance": 2.1},
{"storeId": "456", "stock": 0, "distance": 5.7}
]
}この内部エンドポイントを直接呼び出すことで、HTMLパースのオーバーヘッドを削減しつつ、構造化データを取得できます。ただし、このエンドポイントにもAkamaiの保護が適用されているため、プロキシとTLS偽装は引き続き必要です。
店舗レベル在庫にUS住宅プロキシが必要な理由
Best Buyは米国に約1,000店舗を展開しており、在庫状況は店舗ごとに異なります。Webサイト上の在庫表示は、ユーザーのIPアドレスから推定される地理位置情報に基づいて、最寄り店舗の在庫を表示します。
このため、特定の店舗または地域の在庫を正確に取得するには、その地域に対応するUS住宅IPを使用する必要があります。ProxyHatでは、ユーザー名に地理情報を指定することで、都市レベルのターゲティングが可能です:
# シカゴの住宅IPを使用
http://user-country-US-city-chicago:pass@gate.proxyhat.com:8080
# ロサンゼルスの住宅IPを使用
http://user-country-US-city-los-angeles:pass@gate.proxyhat.com:8080データセンターIPを使用した場合、AkamaiがIPの地理的非一貫性とデータセンター属性を検出し、チャレンジをトリガーする可能性が高くなります。住宅IPは実際のISPに割り当てられたIPアドレスであるため、AkamaiのIPレピュテーションチェックを通過しやすくなります。
ProxyHatの対応ロケーションページで、利用可能な都市レベルのジオターゲティングを確認できます。
Python実装例 — curl_cffi + ProxyHat
以下に、curl_cffiとProxyHatの住宅プロキシを組み合わせて、Best BuyのSKUページから価格を取得し、在庫JSONエンドポイントから店舗在庫を取得する実装例を示します。
ステップ1:必要なパッケージのインストール
pip install curl_cffi parselステップ2:SKUページの取得と価格パース
from curl_cffi import requests
from parsel import Selector
import json
# ProxyHat住宅プロキシ(シカゴ)
proxy = "http://user-country-US-city-chicago:pass@gate.proxyhat.com:8080"
sku = "6523293"
url = f"https://www.bestbuy.com/site/-/{sku}.p?skuId={sku}"
session = requests.Session()
resp = session.get(
url,
proxies={"http": proxy, "https": proxy},
impersonate="chrome120",
timeout=30
)
sel = Selector(resp.text)
price = sel.css(".priceView-customer-price span::text").get()
title = sel.css(".sku-title h1::text").get()
print(f"Title: {title}")
print(f"Price: {price}")ステップ3:在庫JSONエンドポイントの呼び出し
# 在庫JSONエンドポイント
zip_code = "60601"
avail_url = (
f"https://www.bestbuy.com/productfulfillment"
f"?skus={sku}&zip={zip_code}"
)
avail_resp = session.get(
avail_url,
proxies={"http": proxy, "https": proxy},
impersonate="chrome120",
timeout=30
)
avail_data = avail_resp.json()
# 結果(一部省略)
print(json.dumps(avail_data, indent=2)[:500])出力例(truncated):
{
"sku": "6523293",
"price": 199.99,
"inStoreAvailability": true,
"stores": [
{"storeId": "123", "stock": 3, "distance": 2.1},
{"storeId": "456", "stock": 0, "distance": 5.7}
]
}curlでの同等の例
curl -x "http://user-country-US-city-chicago:pass@gate.proxyhat.com:8080" \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
"https://www.bestbuy.com/site/-/6523293.p?skuId=6523293"ローテーション、バックオフ、ページネーション戦略
郵便番号ごとのスティッキーセッション
複数の郵便番号で在庫を確認する場合、各郵便番号に対してスティッキーセッションを使用することで、同じIPで一連のリクエストを送信できます。これにより、Akamaiがセッションの異常を検出するリスクを減らせます。
# 郵便番号60601用のスティッキーセッション
proxy_60601 = "http://user-country-US-city-chicago-session-zip60601:pass@gate.proxyhat.com:8080"
# 郵便番号90001用のスティッキーセッション
proxy_90001 = "http://user-country-US-city-los-angeles-session-zip90001:pass@gate.proxyhat.com:8080"403/Akamaiチャレンジ時のバックオフ
403ステータスコードやAkamaiチャレンジページを受信した場合は、即座にバックオフを行うべきです。指数バックオフ戦略を実装することで、IPのブラックリスト登録を回避できます。
import time
import random
def fetch_with_backoff(url, proxy, session, max_retries=5):
for attempt in range(max_retries):
resp = session.get(
url,
proxies={"http": proxy, "https": proxy},
impersonate="chrome120",
timeout=30
)
if resp.status_code == 200:
return resp
elif resp.status_code == 403:
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"403 received, backing off {wait:.1f}s")
time.sleep(wait)
else:
resp.raise_for_status()
raise Exception(f"Max retries exceeded for {url}")カテゴリページのページネーション
カテゴリページからSKUリストを収集する場合、URLパターン ?cp=<page> を使用してページネーションを行います:
base_url = "https://www.bestbuy.com/site/laptops/abc.c?id=abc"
for page in range(1, 10):
url = f"{base_url}&cp={page}"
resp = fetch_with_backoff(url, proxy, session)
sel = Selector(resp.text)
skus = sel.css(".sku-item::attr(data-sku-id)").getall()
for sku in skus:
process_sku(sku, session, proxy)カテゴリページのスクレイピングでは、リクエスト間隔を2〜5秒程度に保つことで、Akamaiの行動ベースの検出を回避しやすくなります。急激なバーストリクエストはボットシグナルとして検出される可能性があります。
プロキシタイプ比較 — Best Buyスクレイピング向け
| プロキシタイプ | Akamai回避 | ジオターゲティング | 平均レイテンシ | コスト | 推奨用途 |
|---|---|---|---|---|---|
| 住宅プロキシ | ★★★★★ | 都市レベル | 200〜800ms | 中〜高 | 店舗在庫・価格追跡 |
| データセンタープロキシ | ★☆☆☆☆ | 国レベルのみ | 50〜100ms | 低 | 非推奨(即ブロック) |
| モバイルプロキシ | ★★★★★ | 州レベル | 300〜1000ms | 高 | 高難度シナリオ |
Best Buyのスクレイピングでは、住宅プロキシが最適なバランスを提供します。ProxyHatの料金プランでは、住宅プロキシが従量課金制で利用可能です。100並列セッション程度から始めて、対象SKU数と郵便番号カバレッジに応じてスケールすることを推奨します。
倫理と利用規約
Best Buyのスクレイピングを行う際は、以下のガイドラインを遵守してください:
- 公開データのみを対象とする — カタログ価格、公開在庫情報など、ログインなしでアクセスできるデータのみを収集する
- アカウント自動化を避ける — ログイン、カート追加、チェックアウトの自動化は利用規約違反の可能性が高い
- レートを控えめに — サーバーに過度な負荷をかけないよう、リクエスト間隔を適切に設定する
- robots.txtを確認 — Best Buyのrobots.txtを確認し、禁止されているパスを尊重する
米国ではComputer Fraud and Abuse Act (CFAA)がスクレイピングに適用される可能性があります。公開データの収集は一般的に保護されていますが、認証が必要なエリアへのアクセスや、サーバーへの過度な負荷は法的リスクを伴います。EUユーザーのデータを扱う場合はGDPRも考慮が必要です。
公式APIティアで十分な場合は、スクレイピングよりもAPIの使用を優先してください。Best BuyのDeveloper APIは、承認されたキーに対して安定したアクセスを提供し、レート制限内であればサーバー側の変更にも追従しやすくなります。
Key Takeaways
- Best Buyの公式APIは承認制でレート制限が厳しいため、リアルタイム価格と店舗在庫にはHTMLスクレイピングが現実的
- Akamai Bot Manager(_abck, bm_sz Cookie)がデータセンターIPを約3〜5リクエストでブロックするため、US住宅プロキシが必須
- 店舗在庫は地理位置情報に依存するため、都市レベルのジオターゲティング(-country-US-city-chicago)が必要
- curl_cffiによるTLS偽装 + ProxyHat住宅プロキシの組み合わせが、Akamai回避の最適なアプローチ
- 郵便番号ごとのスティッキーセッションと指数バックオフで、ブロックリスクを最小化
- 公開カタログ/価格データのみを対象とし、アカウント自動化は避ける
Best Buyのスクレイピングについてさらに詳しく知りたい方は、WebスクレイピングのユースケースおよびSERPトラッキングのページも参照してください。ProxyHatの設定詳細については公式ドキュメントを参照してください。






