Walmartは、一部商品の価格を変えます。これをプログラムで追いかけようとしたことがあるなら、そのしんどさはきっと分かるはずです。スクリプトが20分くらいは普通に動いていたのに、気づいたら200 OKのレスポンスに見せかけたCAPTCHAページを返し始める、なんてことも珍しくありません。
私はでデータ抽出の仕事をする中で、Walmartのボット対策とかなり向き合ってきました。このガイドでは、2025年時点で本当に使えるやり方、気づかないうちにデータを壊してしまう失敗パターン、そして自作スクレイパー・スクレイピングAPI・ノーコードツールの現実的な使い分けまで、学んだことをまとめて全部共有します。ここでは、3つの抽出方法(HTML解析、__NEXT_DATA__ JSON、内部APIの取得)に加えて、多くのチュートリアルが省いてしまう本番向けのエラーハンドリング、さらに自分に合った方法を選ぶための判断軸まで解説します。Pythonを書く人にも、昼までに価格一覧をスプレッドシートで欲しい人にも役立つ内容です。
なぜPythonでWalmartをスクレイピングするのか?
Walmartは売上高ベースで世界最大級の小売企業で、FY2025の売上はに達し、を守っています。サイト上にはおよそがあり、WalmartのCFOはマーケットプレイス上のにも触れています。さらに、そのなので、カタログの動きがかなり激しく、販売者の入れ替わり、バリエーション変更、在庫変動が毎日のように起こります。

この変動こそ、スクレイピングが大事になる理由です。四半期レポートだけでは、毎晩のスクレイピングでしか拾えない変化は取りこぼします。よくある用途は次のとおりです。
| ユースケース | 必要とする人 | 抽出する情報 |
|---|---|---|
| 競合価格のモニタリング | EC運用担当、価格改定ツール | 価格、プロモーション、MAP遵守状況 |
| 商品カタログの補完 | 営業・販促チーム | 説明文、画像、仕様、バリエーション |
| 在庫状況の追跡 | サプライチェーン担当、ドロップシッパー | 在庫状態、販売者情報 |
| 市場調査・トレンド分析 | マーケティング、プロダクトマネージャー | 評価、レビュー、カテゴリ構成 |
| リード獲得 | 営業チーム | 販売者名、商品数、カテゴリ |
競合価格モニタリングソフトだけでも、市場規模は2025年にに達し、2033年には50.9億ドルまで伸びると予測されています。消費者行動もこの投資を後押ししていて、うえ、83%が複数サイトをまたいで比較検討しています。
この分野ではPythonがほぼ標準です。Apifyの2026年版Infrastructure Reportでは、とされ、主要ライブラリのrequestsはがあります。ある程度まとまった規模でスクレイピングするなら、まずPythonを使うケースが多いでしょう。
Walmartがスクレイピングしづらい理由
Walmartが特に厄介なのは、2種類の商用ボット対策を直列で使っているからです。エッジ側のWAFとTLSフィンガープリント層としてがあり、その後ろで挙動ベースのJavaScriptチャレンジ層としてが動きます。Scrape.doはこの組み合わせを「かなり珍しく、極めて回避しづらい」と表現しています。

しており、Akamai単体でも9/10です。実際の体感でも、だいたいその通りです。
実際に相手にしているのは、次のような仕組みです。
Akamai Bot Manager はTLSフィンガープリント(JA3/JA4ハッシュ)、HTTP/2フレームの並び、ヘッダーの順序や大文字小文字、セッションCookie(_abck、ak_bmsc)をチェックします。素のPython requests は、本物のブラウザでは出ないTLSフィンガープリントを送るため、Walmartのサーバーに届く前にAkamai側で止められます。
PerimeterX/HUMAN はAkamaiの後段で動き、px.jsによるJavaScriptフィンガープリントを実行して、navigatorのプロパティ、canvas描画、WebGL、audio context、さらにマウス移動・スクロール速度・キー入力の癖といった行動生体情報まで見ています。目に見えて分かる失敗例が、悪名高いです。だいたい10秒ボタンを押し続け、その間に行動シグナルを取られます。Oxylabsもかなり率直に、「WalmartはPerimeterX提供の『Press & Hold』型CAPTCHAを使っており、コードだけで解くのはほぼ無理」と述べています。
本当に厄介なのはサイレントブロックです。Walmartは403ではなくHTTP 200でCAPTCHA本文を返すことがあります。、「WalmartはCAPTCHAページを返していても200 OKを返します。リクエスト成功をステータスコードだけで判断してはいけません。」その結果、スクリプトはCAPTCHAのHTMLを「商品が見つからない」と読み違えて、そのまま処理を続けてしまいます。最悪、データセットの半分が壊れていても気づけません。
さらに、店舗スコープのデータ問題もあります。Walmartの価格や在庫は地域依存で、locDataV3やassortmentStoreIdのようなCookieで制御されています。正しいCookieがないと、「全国共通のデフォルト」データが返り、見た目は正しそうでも、実際の表示とはズレます。Cookieが足りない場合はブロックページすら返さず、間違ったデータを静かに返すので、むしろ厄介です。
Walmartからデータを取る3つの方法(比較付き)
手順に入る前に、主要な3つの抽出アプローチを整理しておきます。競合記事の多くは1〜2個しか扱いませんが、ここでは状況に応じて選べるように全部まとめます。
| 方法 | 信頼性 | データの完全性 | ボット対策の難易度 | 保守負荷 |
|---|---|---|---|---|
| HTML + BeautifulSoup | ⚠️ 低い(デプロイのたびにセレクタが壊れる) | 中程度 | 高い | 高い |
__NEXT_DATA__ JSON | ✅ 良い | 高い | 中〜高 | 中程度 |
| 内部APIの取得 | ✅ 最も良い | 最高(バリエーション、在庫、レビュー) | 中〜高 | 低い(構造化JSON) |
| Thunderbit(ノーコード) | ✅ 良い | 高い | 低い(AIが処理) | なし |
WalmartではHTML解析がかなりしんどいです。サイトはNext.jsのバンドルを使っていて、ハッシュ化されたCSSクラス名がデプロイのたびに変わります。__NEXT_DATA__ JSON方式は、2024〜2026年の真面目なオープンソースWalmartスクレイパーが採用している、実用性の高い選択肢です。内部APIの取得は最も強力ですが、多くのチュートリアルが省いている落とし穴があります。そして、カスタムパイプラインが不要ならThunderbitがかなり使いやすいです。
Python環境の準備
必要なものは次のとおりです。
- 難易度: 中級
- 所要時間: セットアップ約30分 + コーディング時間
- 必要なもの: Python 3.10以上、pip、コードエディタ、そして本番運用ならプロキシサービスまたはスクレイピングAPI
プロジェクトフォルダと仮想環境を作成します。
1mkdir walmart-scraper && cd walmart-scraper
2python -m venv venv
3source venv/bin/activate # Windowsの場合: venv\Scripts\Scriptscriptscript activate
必要なライブラリをインストールします。
1pip install curl_cffi parsel beautifulsoup4 lxml
2025年のハードターゲット対策では、curl_cffiが定番です。これはlibcurlのバインディングで、正確なブラウザTLSフィンガープリントを偽装できます。によると、「Walmartはボット検知の一部としてTLSフィンガープリントを使っており、User-Agentを本物っぽく見せるだけでは回避できません。」素のrequestsやhttpxでは、ヘッダーをどれだけ整えてもAkamaiを通過できません。違いを生むのはimpersonate="chrome124"付きのcurl_cffiです。
あわせて、あとで本番パターンで使うjson(標準ライブラリ)、csv(標準ライブラリ)、time、random、loggingもあると便利です。
PythonでWalmartの商品ページをスクレイピングする手順
ステップ1: Walmartの商品ページを取得する
まず必要なのは、即ブロックされないHTTPリクエストを送ることです。2024〜2026年にScrapfly、Scrapingdog、Oxylabs、ScrapeOpsが共通して使っている定番ヘッダーは次のとおりです。
1from curl_cffi import requests
2HEADERS = {
3 "User-Agent": (
4 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
5 "AppleWebKit/537.36 (KHTML, like Gecko) "
6 "Chrome/124.0.0.0 Safari/537.36"
7 ),
8 "Accept": (
9 "text/html,application/xhtml+xml,application/xml;q=0.9,"
10 "image/avif,image/webp,*/*;q=0.8"
11 ),
12 "Accept-Language": "en-US,en;q=0.9",
13 "Accept-Encoding": "gzip, deflate, br",
14 "Upgrade-Insecure-Requests": "1",
15 "Sec-Fetch-Dest": "document",
16 "Sec-Fetch-Mode": "navigate",
17 "Sec-Fetch-Site": "none",
18 "Sec-Fetch-User": "?1",
19 "Referer": "https://www.google.com/",
20}
21session = requests.Session(impersonate="chrome124")
22url = "https://www.walmart.com/ip/Apple-AirPods-Pro-2nd-Generation/1752657021"
23response = session.get(url, headers=HEADERS)
ここで大きな役割を持つのがimpersonate="chrome124"です。これにより、curl_cffiはChrome 124のTLS ClientHello、HTTP/2フレーム順序、pseudo-headerの並びまで合わせます。これがないと、AkamaiはPython特有のJA3ハッシュを見つけて、Walmartのアプリ層に届く前にブロックします。
ブロックされた応答の見分け方: HTMLタイトルに"Robot or human?"が入っている、またはwalmart.com/blockedへリダイレクトされる場合は、すでに止められています。しかもWalmartは、CAPTCHA本文であっても200ステータスを返すことが多いので、response.okだけを見ても意味がありません。
本番運用や繰り返しの利用では、住宅プロキシが必要です。データセンターIPはAkamaiのIPレピュテーションで即座に焼かれます。完全なエラーハンドリングとプロキシ戦略は、後の本番セクションで説明します。
ステップ2: __NEXT_DATA__ JSONから商品データを解析する
Walmart.comはNext.jsアプリケーションで、サーバー描画されたHTMLの中に、単一のscriptタグ <script id="__NEXT_DATA__" type="application/json"> としてハイドレーション用の完全なペイロードを埋め込んでいます。ここがかなりの宝の山です。
「2026年のWalmartはNext.jsを使っており、__NEXT_DATA__ scriptタグ内の構造化JSONから隠れたデータを取る方法は、従来のCSSセレクタ解析より信頼性が高い」と述べています。、、有名なオープンソースWalmartスクレイパーも、この方法を使っています。
抽出方法は以下のとおりです。
1import json
2from parsel import Selector
3sel = Selector(text=response.text)
4raw = sel.xpath('//script[@id="__NEXT_DATA__"]/text()').get()
5data = json.loads(raw)
6product = data["props"]["pageProps"]["initialData"]["data"]["product"]
7idml = data["props"]["pageProps"]["initialData"]["data"].get("idml", {})
多くのチュートリアルはここで終わりますが、実際に必要な項目については以下の完全なJSONパス対応表が役立ちます。2024〜2026年のライブWalmartページで確認済みです。
| データ項目 | JSONパス(initialData 配下) | 型 | 備考 |
|---|---|---|---|
| 商品名 | data > product > name | String | — |
| ブランド | data > product > brand | String | — |
| 現在価格(数値) | data > product > priceInfo > currentPrice > price | Float | 店舗Cookieによって異なる場合あり |
| 現在価格(文字列) | data > product > priceInfo > currentPrice > priceString | String | 例: "$9.99" |
| 短い説明 | data > product > shortDescription | HTML String | テキスト化するならBeautifulSoupで解析 |
| 長い説明 | data > idml > longDescription | HTML String | product ではなく idml にある — 古いチュートリアルがよく間違えるポイント |
| 画像一覧 | data > product > imageInfo > allImages | Array | {id, url} の配列 |
| 平均評価 | data > product > averageRating | Float | 旧式の rating ではなく averageRating |
| レビュー数 | data > product > numberOfReviews | Integer | — |
| バリエーション | data > product > variantCriteria | Array | サイズや色などの選択肢 |
| 在庫状況 | data > product > availabilityStatus | String | IN_STOCK、OUT_OF_STOCK、LIMITED_STOCK |
| 販売者 | data > product > sellerDisplayName | String | — |
| 製造元 | data > product > manufacturerName | String | — |
特に注意したいのがlongDescriptionの位置です。2023年のScrapeHero記事ではproduct.longDescriptionとしていましたが、2024年以降のソースでは一貫して兄弟キーのidml側に置かれています。必ず先にidml.longDescriptionを見て、古いページだけproduct.longDescriptionへフォールバックするのが安全です。
.get()をつないで安全に取るなら、こう書けます。
1def extract_product(data):
2 product = data["props"]["pageProps"]["initialData"]["data"]["product"]
3 idml = data["props"]["pageProps"]["initialData"]["data"].get("idml", {})
4 price_info = product.get("priceInfo", {})
5 current_price = price_info.get("currentPrice", {})
6 image_info = product.get("imageInfo", {})
7 return {
8 "name": product.get("name"),
9 "brand": product.get("brand"),
10 "price": current_price.get("price"),
11 "price_string": current_price.get("priceString"),
12 "short_desc": product.get("shortDescription"),
13 "long_desc": idml.get("longDescription", product.get("longDescription")),
14 "images": [img.get("url") for img in image_info.get("allImages", [])],
15 "rating": product.get("averageRating"),
16 "review_count": product.get("numberOfReviews"),
17 "variants": product.get("variantCriteria"),
18 "availability": product.get("availabilityStatus"),
19 "seller": product.get("sellerDisplayName"),
20 "manufacturer": product.get("manufacturerName"),
21 }
JSONパスを自分で追いたくない人には、がページを自動で見分け、これらの項目を構造化してくれます。手動でパスを指定する必要はありません。「AIで項目を提案」をクリックするとページを読み取り、表を作ってくれます。カスタムパイプラインを作るなら、上のマップが基準になります。
ステップ3: Walmartの内部APIエンドポイントを取得して、より豊富なデータを取る
この方法をちゃんと扱っている競合記事はほとんどありません。最も強力ですが、同時に最も複雑な抽出ルートです。
Walmartのフロントエンドは、を呼び出しています。エンドポイントはwww.walmart.com/orchestra/*配下にあります。
/orchestra/pdp/graphql/...— 商品詳細のハイドレーションとバリアント切り替え/orchestra/snb/graphql/...— 検索・閲覧のページネーション/orchestra/reviews/graphql/...— ページ分割されたレビュー
これらは、__NEXT_DATA__では取り切れない、よりきれいで構造化されたJSONを返します。たとえば、バリエーションごとの価格、リアルタイム在庫、レビューの全ページなどです。
多くのブログ記事がぼかしている注意点: Walmartはを使っています。リクエスト本文にはクエリ文字列ではなく、SHA-256ハッシュ(persistedQuery.sha256Hash)だけが送られます。このハッシュがサーバー側で知られていないと、PersistedQueryNotFoundになります。しかもWalmartはデプロイ時にこのハッシュを更新します。高名なオープンソースWalmartスクレイパーが/orchestra/コードをそのまま使える形で公開していないのは、このためです。
現実的で正直なやり方は、DevToolsで調べることです。
- ChromeでWalmartの商品ページを開く
- DevToolsを開き、Networkタブで「Fetch/XHR」に絞る
- 普段どおりページを操作する — バリエーションをクリックする、レビューまでスクロールする、店舗を変える
- 商品データを返す
/orchestra/*へのJSONリクエストを探す - リクエストを右クリックして「Copy as cURL」を選ぶ
- そのcURLを
curl_cffiでPythonに移す
APIを再現するコード例は以下です。
1import json
2from curl_cffi import requests
3session = requests.Session(impersonate="chrome124")
4# まず商品ページを開いてセッションを温める
5session.get("https://www.walmart.com/ip/some-product/1234567", headers=HEADERS)
6# その後、DevToolsからコピーした内部API呼び出しを再現する
7api_url = "https://www.walmart.com/orchestra/pdp/graphql"
8api_headers = {
9 **HEADERS,
10 "accept": "application/json",
11 "content-type": "application/json",
12 "referer": "https://www.walmart.com/ip/some-product/1234567",
13 "wm_qos.correlation_id": "コピーしたcorrelation-id",
14}
15payload = {
16 # DevToolsから取得したリクエスト本文をそのまま貼る
17 "variables": {"productId": "1234567"},
18 "extensions": {
19 "persistedQuery": {
20 "version": 1,
21 "sha256Hash": "コピーしたハッシュ"
22 }
23 }
24}
25api_response = session.post(api_url, headers=api_headers, json=payload)
26api_data = api_response.json()
セッションのウォーミングアップはかなり重要です。WalmartのPerimeterX Cookie(_px3、_pxhd、ACID)は、最初のHTML取得でセットされていないとAPIが通りません。これがないと、412や403が返ってきます。
この方法を使うべき場面: __NEXT_DATA__に入っていないデータが必要なとき、たとえばバリエーション別の詳細価格、最初の一括取得を超えるレビューのページネーション、リアルタイム在庫数などです。ほとんどの用途では__NEXT_DATA__で十分で、ずっと簡単です。
Walmartの検索結果と複数ページをスクレイピングする
検索結果も同様に__NEXT_DATA__を使いますが、JSONパスが少し違います。
1search_url = "https://www.walmart.com/search?q=laptops&page=1"
2response = session.get(search_url, headers=HEADERS)
3sel = Selector(text=response.text)
4raw = sel.xpath('//script[@id="__NEXT_DATA__"]/text()').get()
5data = json.loads(raw)
6search_result = data["props"]["pageProps"]["initialData"]["searchResult"]
7items = search_result["itemStacks"][0]["items"]
8# スポンサー商品を除外する
9organic_items = [i for i in items if i.get("__typename") == "Product"]
10for item in organic_items:
11 print(item.get("name"), item.get("priceInfo", {}).get("currentPrice", {}).get("price"))
ページネーションはpageパラメータを増やすだけです。&page=1、&page=2という形ですね。ただし、公開されていない制限として、Walmartは実際の総件数に関係なく検索結果を25ページまでに制限しています。、「Walmartはアクセス可能な結果ページの最大数を、総ページ数にかかわらず25に設定している」とされています。
より深くカバーするための回避策は次のとおりです。
- 並び順を切り替える: 同じ検索語で
&sort=price_lowと&sort=price_highを使い、約50ページ分のカバーを狙う - 価格帯で分ける:
&min_price=X&max_price=Yを追加し、カタログを細かく分割する - カテゴリで分ける: サイト全体ではなく、特定カテゴリ内で検索する
itemStacksが配列である点にも注意が必要です。Scrapflyのリポジトリでは [0] を固定していますが、カテゴリページやブラウズページには「Top picks」「More results」のように複数スタックが入ることがあります。より堅牢なのは、全部のスタックを回す方法です。
1for stack in search_result.get("itemStacks", []):
2 for item in stack.get("items", []):
3 if item.get("__typename") == "Product":
4 # itemを処理する
5 pass
ちなみに、Walmartのrobots.txtではされています。商品詳細ページ(/ip/...)や多くのカテゴリページ(/cp/...)は禁止対象ではありません。コンプライアンスが気になるなら、まずは検索結果よりも商品ページやカテゴリツリーから始めるのが無難です。
サイレントブロックでデータを壊さないための、本番向けエラーハンドリング
多くのチュートリアルはここで崩れます。1ページを取って1商品を解析したら終わり、という内容だからです。実運用では何千ページも取り、その間Walmartは本気で止めに来ます。デモ用スクレイパーと実際に動くスクレイパーの差は、失敗時の扱い方にあります。
サイレントブロックをデータ汚染の前に検知する
Walmartスクレイパーでかなり重要なのが、ブロック検知関数です。、、、の見解をまとめると、独立した4つのチェックが必要です。
1BLOCK_MARKERS = (
2 "Robot or human",
3 "Press & Hold",
4 "Press & Hold",
5 "px-captcha",
6 "perimeterx",
7)
8def is_walmart_blocked(response) -> bool:
9 # 1. 専用ブロック先へのリダイレクト
10 if "/blocked" in str(response.url):
11 return True
12 # 2. 明確なステータスコード
13 if response.status_code in (403, 412, 428, 429, 503):
14 return True
15 # 3. 200 OKだがCAPTCHA本文(サイレントブロック)
16 body = response.text or ""
17 if any(m.lower() in body.lower() for m in BLOCK_MARKERS):
18 return True
19 # 4. レスポンス長の健全性チェック — 本物のPDPは通常300〜900KB
20 if len(response.content) < 50_000 and "/ip/" in str(response.url):
21 return True
22 return False
4つ目のチェック、つまりレスポンス長は、Walmartが目立つCAPTCHA文言を含まない軽いページを返していても、必要な商品データが入っていないケースを拾うのに役立ちます。
指数バックオフ + ジッターで再試行する
リクエスト失敗時に、すぐWalmartへ連打するのは避けるべきです。定番は、再試行のタイミングをずらすために、指数バックオフにジッターを足すやり方です。
1import time
2import random
3import logging
4from curl_cffi import requests as cffi_requests
5log = logging.getLogger("walmart")
6def fetch_with_retry(session, url, max_retries=5, base_delay=2, max_delay=60):
7 for attempt in range(max_retries):
8 try:
9 response = session.get(url, headers=HEADERS, timeout=15)
10 if response.status_code in (429, 503):
11 raise Exception(f"Throttled: {response.status_code}")
12 if is_walmart_blocked(response):
13 raise Exception("Silent block detected")
14 return response
15 except Exception as e:
16 if attempt == max_retries - 1:
17 raise
18 wait = min(max_delay, base_delay * (2 ** attempt)) + random.uniform(0, 3)
19 log.warning(f"Attempt {attempt + 1} failed: {e}. Retrying in {wait:.1f}s")
20 time.sleep(wait)
21 return None
ここでのジッター(random.uniform(0, 3))は飾りではありません。複数のワーカーが同じ秒に一斉再試行して、Akamaiの速度検知に引っかかるのを防ぎます。
レート制限
とはどちらも、Walmartに対しては1リクエストあたり3〜6秒のランダム遅延に落ち着いています。「ページ読み込みの間に3〜6秒待ち、遅延時間をランダム化する」ことが推奨されています。
1import time
2import random
3def rate_limited_fetch(session, url):
4 response = fetch_with_retry(session, url)
5 time.sleep(random.uniform(3.0, 6.0))
6 return response
規模が大きいなら、非同期のレート制御にaiolimiterを使うのもありです。
1from aiolimiter import AsyncLimiter
2limiter = AsyncLimiter(max_rate=10, time_period=60) # 1分あたり10リクエスト
データ検証
レスポンスがブロックされていなくても、解析結果が間違っていることはあります(店舗違い、ペイロード劣化など)。出力前に検証しましょう。
1def validate_product(product):
2 """商品データが妥当ならTrueを返す。"""
3 if not product.get("name"):
4 return False
5 price = (product.get("priceInfo") or {}).get("currentPrice", {}).get("price")
6 if not isinstance(price, (int, float)) or price <= 0:
7 return False
8 if product.get("availabilityStatus") not in ("IN_STOCK", "OUT_OF_STOCK", "LIMITED_STOCK"):
9 return False
10 return True
セッションログの記録
セッションごとの成功率を追ってください。10分間で80%を下回ったら、何かが変わっています。IPが焼かれた、Cookieが期限切れになった、あるいはWalmartが新しいボット対策を入れた可能性があります。
1class ScrapeMetrics:
2 def __init__(self):
3 self.total = 0
4 self.success = 0
5 self.blocks = 0
6 self.errors = 0
7 def record(self, result):
8 self.total += 1
9 if result == "success":
10 self.success += 1
11 elif result == "blocked":
12 self.blocks += 1
13 else:
14 self.errors += 1
15 @property
16 def success_rate(self):
17 return (self.success / self.total * 100) if self.total > 0 else 0
18 def check_health(self):
19 if self.total > 20 and self.success_rate < 80:
20 log.critical(f"Success rate dropped to {self.success_rate:.1f}% — consider rotating proxies or pausing")
派手ではありませんが、データ品質を守るにはかなり大事です。
自作Python vs. Scraping API vs. ノーコード: Walmartに最適な方法を選ぶ
多くの開発者は、「本当にそれが最善か」を考えずに、いきなり自作スクレイパーを書き始めます。しています。フォーラムでは「実質9/10だ」とか「専用のWebスクレイピングAPIって大げさじゃない?」という声もあります。答えは、件数、予算、エンジニアリング余力次第です。
| 要素 | 自作Python(requests + プロキシ) | スクレイピングAPI(Oxylabs、Bright Dataなど) | ノーコードツール(Thunderbit) |
|---|---|---|---|
| 最初の1行を取るまでの時間 | 数時間 | 15〜60分 | 約2分 |
| 本番運用までの時間 | 40〜80時間 | 4〜16時間 | 約30分 |
| ボット対策対応 | 自分で対応(難しい) | ベンダーが対応 | 自動対応 |
| 小規模コスト(<月1,000ページ) | 低い(プロキシ費は約4〜8ドル/GB) | 月40〜49ドル程度の入門プラン | 無料〜15ドル/月 |
| 大規模コスト(月10万ページ以上) | 1件あたりは安い | 1件あたりは高め | 変動あり |
| カスタマイズ性 | 完全に自由 | APIパラメータ次第 | UI/項目定義の範囲内 |
| 継続保守 | 月4〜8時間 | ほぼ不要 | なし(AIが追従) |
| 向いている人 | 自前パイプラインを作る開発者 | 中規模の本番スクレイピング | ビジネスユーザー、短期の単発抽出 |
自作Pythonが向いているケース
すでにプロキシ契約がある、ヘッダーや郵便番号ターゲット、販売者セグメントを細かく制御したい、月に何百万ページも扱うのでAPIの従量課金が積み上がる、オンプレミスやコンプライアンス要件がある、こういう場合は自作が有利です。代わりに、それなりの実装工数が必要です。ページネーション、再試行、プロキシローテーション、TLS偽装、複数ページ種別のスキーマ対応を備えた本番用Scrapyスパイダーは、に加え、Walmartがフィンガープリントを更新するたびに月4〜8時間の保守がかかります。
スクレイピングAPIが時間を節約してくれるケース
スクレイピングAPIはボット対策層を代わりに処理してくれます。では、Walmartでの成功率は 、**Scrape.doが98%**とされています。、、のようなツールは、入門価格が月40〜49ドルくらいです。2〜5人のエンジニアで、月1万〜100万ページ規模なら、APIを選ぶのがかなり現実的です。1リクエストごとのコストと引き換えに、保守はほぼゼロになります。
ノーコードが正解のケース
はまったく別のニーズに向いています。PM、アナリスト、EC運用担当で、来週ではなく今日の午後にWalmartの商品データをスプレッドシートへ入れたいなら、ノーコードが率直な答えです。
使い方は、を入れて、Walmartの商品ページまたは検索ページを開き、「AIで項目を提案」をクリックします。ThunderbitのAIがページを読み取り、商品名・価格・評価などの列を提案します。「スクレイプ」を押せば表にデータが入ります。Excel、Google Sheets、Airtable、Notionへエクスポートできて、しかも無料です。
Thunderbitはクラウド側でボット対策を処理するので、CAPTCHAやプロキシ、TLSフィンガープリントを気にしなくて済みます。レイアウト変更にもAIが自動で追従するため、保守もほぼ不要です。JSONパスを自分で追いたくない人には、いちばん手間の少ない選択肢です。
ただし、正直な制約もあります。Thunderbitは1日10万ページ以上の用途には向きません。クレジット予算とクラウド上限の関係で、大量取り込みは生のAPIより割高になります。また、ツールが対応していなければ、特定の郵便番号やASNを固定することもできません。継続的で高ボリュームなパイプラインなら、やはり自作かスクレイピングAPIが向いています。
ざっくりした料金感: ThunderbitでWalmartの商品1,000行を取る場合、約2,000クレジットで、Starter/Proプランだとおよそ0.60〜1.10ドルです。低ボリュームなら、OxylabsのWalmart APIと同等か、それより安いこともあります。で最新情報を確認してください。
スクレイピングしたWalmartデータの出力方法
データを取ったら、使いやすい形で保存する必要があります。よく使われるのは次の3形式です。
CSV — アナリストが実際に開く、いちばん無難な形式です。
1import csv
2def export_csv(products, filename="walmart_products.csv"):
3 fieldnames = ["name", "price", "availability", "rating", "review_count", "seller", "url"]
4 with open(filename, "w", newline="", encoding="utf-8-sig") as f:
5 writer = csv.DictWriter(f, fieldnames=fieldnames, quoting=csv.QUOTE_MINIMAL)
6 writer.writeheader()
7 for p in products:
8 writer.writerow({k: p.get(k) for k in fieldnames})
Excelとの相性のため、utf-8-sigを使います。BOMがあることで、Excelが特殊文字を壊しにくくなります。
JSONL — スクレイピングパイプラインの本番向け形式です。
1import json
2import gzip
3def export_jsonl(products, filename="walmart_products.jsonl.gz"):
4 with gzip.open(filename, "at", encoding="utf-8") as f:
5 for p in products:
6 f.write(json.dumps(p, ensure_ascii=False) + "\n")
(書き込み中断があっても最後の1行だけ失う)、一定メモリでストリーミングでき、バリエーションやレビューのような入れ子データもそのまま保てます。
Excel — 一度きりの引き渡しに向いています。
1from openpyxl import Workbook
2def export_excel(products, filename="walmart_products.xlsx"):
3 wb = Workbook(write_only=True)
4 ws = wb.create_sheet("Products")
5 ws.append(["Name", "Price", "Availability", "Rating", "Reviews", "Seller"])
6 for p in products:
7 ws.append([p.get("name"), p.get("price"), p.get("availability"),
8 p.get("rating"), p.get("review_count"), p.get("seller")])
9 wb.save(filename)
Thunderbitは、Pythonを使わない人向けのエクスポート体験もカバーしています。Google Sheets、Airtable、Notion、Excel、CSV、JSONへワンクリックで出力でき、ベースプランでも無料です。継続的な監視には、Thunderbitのスケジュールスクレイパー機能で定期抽出も自動化できます。
スケジューリングでひとつ注意するなら、。GitHub ActionsのランナーはAzureのIPレンジ上にあり、Walmartのボット対策にすぐブロックされます。APScheduerをVPSで動かすか、通信を全部住宅プロキシ経由にしてください。
Walmartスクレイピングの法的・倫理的ガイドライン
フォーラムの利用者も、この点はかなり気にしています。「開発者とのいたちごっこはまだしも、法務チーム相手は怖い」という感じです。
Walmartの利用規約では、、「事前の書面による明示的な同意」がない限り、ロボット、スパイダー、その他の手動・自動手段で素材を取得・索引化・『scrape』・『data mine』・収集することを禁じています。
Walmartのrobots.txtでは、、/account、/api/、多数の内部エンドポイントがされています。一方で、商品詳細ページ(/ip/...)やレビュー(/reviews/product/)は禁止対象ではありません。
hiQ v. LinkedInの前例(第9巡回区控訴裁判所、)では、公開情報のスクレイピングが連邦CFAAに違反する可能性は低いとされました。ただし同じ裁判で、hiQはLinkedInの利用規約に違反したとされ、が出ています。2024年のより新しい判決(、)ではCFAAの適用範囲がさらに狭まり、著作権の優先排除に関する防御も示されましたが、これらはWalmartにそのまま当てはまるわけではなく、個別の利用規約文言に依存します。
実務上の指針: サーバーに負荷をかけない。レート制限を守る。個人データやユーザーデータは取らない。データは責任を持って扱う。少量の公開Walmart商品ページを個人研究のために取るのと、Walmartの規約に反して商用規模で集めるのとでは、リスクがまるで違います。Walmartデータを使って製品を作るなら、弁護士に相談し、Walmartの公式も検討してください。
免責事項: これは教育目的の情報であり、法律相談ではありません。
まとめと重要ポイント
PythonでWalmartをスクレイピングするのは、です。AkamaiとPerimeterXの二重ボット対策があるからです。無理ではありませんが、ちゃんとしたツールとやり方が必要です。
重要なポイント:
__NEXT_DATA__JSONの抽出が、ほとんどの用途でいちばん実用的です。2024〜2026年の主要なオープンソースWalmartスクレイパーは、ほぼこれを使っています。PDPではprops.pageProps.initialData.data.product、検索・閲覧ではsearchResult.itemStacksが基本パスです。impersonate="chrome124"付きのcurl_cffiは必須です。素のrequestsやhttpxでは、ヘッダーを整えてもAkamaiのTLSフィンガープリント検知を突破できません。- 本当に怖いのはサイレントブロックです。Walmartは200 OKでCAPTCHA本文を返します。ステータスコードだけでなく、レスポンス本文も見てください。
- 本番スクレイパーには、うまくいく前提のコード以上が必要です。指数バックオフとジッター、4シグナルでのブロック検知、1リクエストあたり3〜6秒のレート制限、データ検証、セッション健全性の監視が必須です。
/orchestra/*経由の内部API取得は強力ですが壊れやすいです。メイン手法ではなく、特定データが必要なときのDevTools調査として使いましょう。- Walmartの検索結果は25ページで打ち止めです。並び順の切り替えや価格帯分割でカバー範囲を広げてください。
- 方法は正直に選ぶべきです。カスタム要件と大規模処理がある開発者には自作Python。中規模チームでスクレイピング担当がいないならAPI。は、今日の午後にGoogle Sheetsへデータが欲しいビジネスユーザー向けです。
ノーコードで試したいなら、には無料枠があります。Walmartのページをいくつかスクレイピングして結果を確かめられます。Pythonで進めるなら、この記事のコードパターンは本番で検証済みです。どちらの道を選んでも、Walmartの防御と、それを抜ける3つの道筋が見えるはずです。
Webスクレイピングの他の手法については、、、もご覧ください。ではチュートリアル動画も公開しています。
FAQ
Walmartの商品データをスクレイピングするのは合法ですか?
Walmartの利用規約では、書面による同意なしの自動スクレイピングは禁止されています。第9巡回区のhiQ v. LinkedIn判決(2022年)では、公開ページのスクレイピングに連邦CFAAが適用される可能性は低いとされましたが、同じ事件はスクレイパー側に対するで終わっています。個人研究のために公開商品ページを少量取るのと、商用規模で抽出するのとでは、リスクがかなり違います。Walmartデータで事業を作るなら、弁護士に相談してください。
Walmartスクレイパーが頻繁にブロックされるのはなぜですか?
よくある原因は、素のrequestsやhttpxを使っていること(Python固有のTLSフィンガープリントが即座にAkamaiに検知される)、ヘッダー不足または不適切、プロキシローテーションなし、1ページあたり3〜6秒より速いリクエスト、セッションCookie(_px3、_abck、locDataV3)の欠落です。impersonate="chrome124"付きのcurl_cffiに切り替え、住宅プロキシを使い、この記事で説明したブロック検知と再試行のパターンを実装してください。
PythonでWalmartからどんなデータが取れますか?
商品名、価格(現在価格と値下げ前価格)、画像、短い説明、長い説明、評価、レビュー数、在庫状況、販売者名、製造元情報、バリエーション(サイズ、色)、カテゴリ上の位置などです。__NEXT_DATA__方式を使えば、これらはすべて構造化JSONとして取れます。内部APIの取得を使えば、さらにバリエーション別価格、リアルタイム在庫、ページ分割されたレビューも取れます。
Walmartをスクレイピングするのにプロキシは必要ですか?
はい。本番運用や繰り返し利用では必要です。 — ヘッダーが完璧でも、非住宅IPはAkamaiのIPレピュテーションで弾かれます。住宅プロキシまたはモバイルプロキシが必須です。データセンターIPはかなり早く焼かれます。プロキシ業者やプランにもよりますが、1,000ページあたり約3〜17ドルを見込んでください。
コードを書かずにWalmartをスクレイピングできますか?
できます。はAI搭載のChrome拡張で、2クリックでWalmartをスクレイピングできます。まず「AIで項目を提案」で商品データ列を自動検出し、次に「スクレイプ」で抽出します。クラウドでボット対策を処理し、Excel、Google Sheets、Airtable、Notionへ直接エクスポートできて、しかも無料です。カスタムパイプラインを作らずにすぐデータが欲しいアナリスト、PM、ビジネスユーザーにぴったりです。大規模または高度にカスタマイズされたスクレイピングには、PythonまたはスクレイピングAPIが引き続き有力です。
詳しくはこちら