私のAmazonレビュー用スクレイパーは、6週間ものあいだ完璧に動いていました。ところがある朝、返ってきたのは 200 OK と、何も入っていないページだけ。エラーでもCAPTCHAでもなく、以前は何百件ものレビューが並んでいた場所が、空っぽのHTMLになっていたのです。
もしこの状況に見覚えがあるなら、あなただけではありません。2025年後半、Amazonはレビュー全文ページにログイン必須の壁を導入し、その影響で大量のPythonスクレイピングスクリプトが一夜にして動かなくなりました。私はここ数か月、ThunderbitでAIスクレイパーの開発に取り組む一方、自分自身のPythonレビュー取得パイプラインも維持してきました。その両面からこの問題に向き合ってきたので、スクリプトが止まったときに本当はこういう記事が欲しかった、という内容をまとめようと思ったのです。この記事では、実際に動く手順として、Cookieベース認証、AmazonのCSS難読化を回避できる安定したセレクター、10ページ制限への対処法、ボット対策、さらにレビュー本文を実際のビジネスインサイトに変える感情分析まで解説します。途中で「ここまでコードを保守するのはちょっと大変だな」と感じたら、同じ処理をPython不要で約2分でこなすThunderbitの方法も紹介します。
Amazonレビューのスクレイピングとは?なぜ重要なのか?
Amazonレビューのスクレイピングとは、商品ページから星評価、レビュー本文、投稿者名、投稿日、Verified Purchaseバッジなどの顧客レビュー情報をプログラムで抽出することです。Amazonは2010年にProduct Advertising APIからレビュー内容を削除して以来、それを戻していないため、このデータをプログラムで取得するにはWebスクレイピングしかありません。
数字を見ても、その重要性は明らかです。95%の購入者が購入前にレビューを読むうえ、94%がAmazonを商品レビューの第一情報源として挙げているからです。商品ページにレビューを5件だけ表示するだけでもコンバージョン率が270%向上することがあります。レビュー感情を体系的に分析している企業では、顧客維持率が最大15%向上するという報告もあります。これは抽象的なデータサイエンスの話ではなく、競合分析、製品改善のヒント、マーケティングで使える生の言葉が、Amazonのサーバー上にそのまま眠っているということです。
なぜPythonでAmazonレビューを取得するのか
この用途では、今でもPythonが最有力です。2024年のStack Overflow開発者調査で最も「使いたい」と答えられた言語であり、requests、BeautifulSoup、pandas、Scrapy などのエコシステムがあるため、専業開発者でなくてもWebスクレイピングに取り組みやすいからです。
チームごとに、このデータの使い方はさまざまです。
| チーム | 用途 | 抽出する情報 |
|---|---|---|
| 製品 / R&D | 繰り返し出る不満を特定し、改善の優先順位を決める | 星1〜2レビュー本文、頻出キーワード |
| 営業 | 競合商品の評価傾向を監視する | 評価、レビュー件数の推移 |
| マーケティング | 広告コピーに使える顧客の言葉を集める | ポジティブな表現、機能への言及 |
| EC運用 | 自社商品の評価推移を追跡する | 星分布、Verified Purchase比率 |
| 市場調査 | カテゴリー上位商品の特徴を比較する | 複数ASINのレビューセット |
あるキッチン用品ブランドはネガティブレビューを分析し、「ノンスティック加工が剥がれる」という指摘が22%を占めることを発見し、製品を改良した結果、60日以内に再びカテゴリ1位のベストセラーを獲得しました。あるフィットネストラッカー企業はレビュー本文から「バンドが肌に合わない」という声を見つけ、ラテックスアレルギーの問題を特定して低刺激版を投入し、返品率を40%削減しました。こうした成果があるからこそ、エンジニアリングの手間をかける価値があるのです。
ログイン壁:Amazonレビュー用スクレイパーが動かなくなった理由
2024年11月14日、Amazonは商品レビュー全文ページを閲覧する際にサインインを必須にし始めました。この変更はコミュニティフォーラムやスクレイピング関連ベンダーのブログでも確認されています。シークレットウィンドウで /product-reviews/{ASIN}/ にアクセスすると、レビューではなくサインインページへリダイレクトされます。

症状は分かりにくいです。スクリプトは 200 OK を受け取るのに、HTML本文にはレビューの代わりにログインフォーム(name="email"、id="ap_password")が入っている。エラーコードは出ません。CAPTCHAも出ません。ただ、何も役に立つものが返ってこないだけです。
Amazonがこれを行った理由は、ボット対策と地域ごとの規制対応です。実際の適用にはばらつきがあり、特に1ページ目では壁がかかる前に数件のレビューだけ見えてしまうこともありますが、本格的にスクレイピングするなら、常に壁がある前提で考えるべきです。
Amazonの各国ドメイン(.de、.co.uk、.co.jp など)は、それぞれ個別にこの制限を適用しています。あるフォーラムユーザーの言葉を借りれば、「国ごとにログインが必要」です。.com のCookieは .co.uk では使えません。
目玉レビューと全文レビュー:ログインなしで今も取れるもの
Amazonの商品ページ(/dp/{ASIN}/)では、認証なしでもおよそ8件の「目玉レビュー」が表示されます。これはAmazonのアルゴリズムが選んだレビューで、ざっと雰囲気をつかむには便利ですが、並び替えや絞り込み、ページ送りはできません。
全文レビューのページ(/product-reviews/{ASIN}/)は、新着順の並び替え、星評価でのフィルタリング、何百件にも及ぶページネーションを使うにはログインが必要です。
もし数件だけをざっくり確認したいなら、商品ページを取得すれば十分です。何百件、何千件と取りたいなら、認証対応が必須になります。
事前準備:Python環境と必要なライブラリ
コードを書く前に、まずは以下を用意します。
- 難易度: 中級(Pythonに慣れていて、HTMLの基本を理解している方向け)
- 所要時間: სრულიパイプラインで約45分、基本的な取得だけなら約10分
- 必要なもの: Python 3.8以上、Chromeブラウザ、有効なAmazonアカウント
主要ライブラリをインストールします。
pip install requests beautifulsoup4 lxml pandas textblob
必要に応じて、より高度な感情分析用にこちらも使えます。
pip install transformers torch
ASINとは? Amazonの商品識別子で、10文字のコードです。商品URLの中に必ず入っています。たとえば amazon.com/dp/B0BCNKKZ91 なら、ASINは B0BCNKKZ91 です。これをレビューURLに差し込みます。
ステップ1:Cookieベース認証でログイン壁を越える
最も安定した方法は、ブラウザでAmazonにログインし、セッションCookieをコピーして、Pythonの requests.Session() に入れるやり方です。これなら、Seleniumでログインを自動化したときに発生しがちなCAPTCHAやSMSの2要素認証を回避できます。
必要なCookieは次の7つです。
| Cookie名 | 役割 |
|---|---|
session-id | 変動するセッション識別子 |
session-id-time | セッションのタイムスタンプ |
session-token | 変動するセッショントークン |
ubid-main | ユーザーの閲覧識別子 |
at-main | 主要な認証トークン |
sess-at-main | セッション単位の認証情報 |
x-main | メールアドレスに紐づく識別子 |
Chrome DevTools から Cookie を取り出す方法
- Chromeで amazon.com にログインする
- DevTools を開く(F12 または右クリック → 検証)
- Application → Storage → Cookies →
https://www.amazon.comに進む - 表にある各Cookie名を見つけて値をコピーする
- Python用にセミコロン区切りの文字列として整える
セッションは次のように設定します。
import requests
session = requests.Session()
# ここにCookieの値を貼り付ける
cookies = {
"session-id": "YOUR_SESSION_ID",
"session-id-time": "YOUR_SESSION_ID_TIME",
"session-token": "YOUR_SESSION_TOKEN",
"ubid-main": "YOUR_UBID_MAIN",
"at-main": "YOUR_AT_MAIN",
"sess-at-main": "YOUR_SESS_AT_MAIN",
"x-main": "YOUR_X_MAIN",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
}
session.cookies.update(cookies)
session.headers.update(headers)
重要: 以降のすべてのリクエストで同じ session オブジェクトを使い回してください。こうすることでCookieの整合性が保たれ、実際のブラウザ操作に近い挙動になります。Cookieの有効期限は、スクレイピング負荷が高くなければ通常数日〜数週間は持ちますが、再びログイン画面に飛ばされるようなら、ブラウザからCookieを取り直してください。
.com 以外のマーケットプレイスではCookie名が少し変わります。たとえば amazon.de では at-main の代わりに at-acbde、amazon.co.uk では at-acbuk を使います。マーケットプレイスごとに独立したセッションが必要です。
ステップ2:リクエストを作成し、BeautifulSoupでレビューHTMLを解析する
AmazonレビューのURLは次の形式です。
https://www.amazon.com/product-reviews/{ASIN}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber=1
基本となる関数は次の通りです。
from bs4 import BeautifulSoup
import time, random
def get_soup(session, url):
time.sleep(random.uniform(2, 5)) # 丁寧な間隔を入れる
response = session.get(url, timeout=15)
# ログイン壁の検知
if "ap_email" in response.text or "Amazon Sign-In" in response.text:
raise Exception("ログイン壁を検知しました — Cookieを更新してください")
if response.status_code != 200:
raise Exception(f"HTTP {response.status_code}")
return BeautifulSoup(response.text, "lxml")
ひとつ効く小技があります。レビューURLに行く前に、先に商品ページへアクセスしてください。そうすると、セッション内で自然な閲覧パターンが作れます。
# 先に商品ページへアクセスする(通常の閲覧に近づける)
product_url = f"https://www.amazon.com/dp/{asin}"
session.get(product_url, timeout=15)
time.sleep(random.uniform(1, 3))
# その後でレビュー一覧へアクセスする
reviews_url = f"https://www.amazon.com/product-reviews/{asin}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber=1"
soup = get_soup(session, reviews_url)
ステップ3:安定したセレクターでレビュー情報を抽出する(CSSクラス頼みはやめる)
ここで、多くの2022〜2023年の解説記事は破綻します。AmazonはCSSクラス名を難読化しており、定期的に変わります。あるフォーラムでは、困った開発者が「spanタグのクラス名に共通パターンがまったく見つからなかった」と嘆いていました。
解決策は、レビュー要素に付いている data-hook 属性を使うことです。これは驚くほど安定しています。Amazonのフロントエンド自身が依存している意味ベースの識別子なので、ランダム化されにくいのです。
| レビュー項目 | 安定したセレクター(data-hook) | 壊れやすいセレクター(class) |
|---|---|---|
| レビュー本文 | [data-hook="review-body"] | .review-text-content(変わりやすい) |
| 星評価 | [data-hook="review-star-rating"] | .a-icon-alt(曖昧) |
| レビュータイトル | [data-hook="review-title"] | .review-title(場合による) |
| 投稿者名 | span.a-profile-name | 比較的安定 |
| 投稿日 | [data-hook="review-date"] | .review-date(地域差あり) |
| Verified Purchase | [data-hook="avp-badge"] | span.a-size-mini |
data-hook を使った抽出コードはこちらです。
import re
def extract_reviews(soup):
reviews = []
review_divs = soup.select('[data-hook="review"]')
for div in review_divs:
# 星評価
rating_el = div.select_one('[data-hook="review-star-rating"]')
rating = None
if rating_el:
rating_text = rating_el.get_text(strip=True)
match = re.search(r'(\d\.?\d?)', rating_text)
if match:
rating = float(match.group(1))
# タイトル
title_el = div.select_one('[data-hook="review-title"]')
title = title_el.get_text(strip=True) if title_el else ""
# 本文
body_el = div.select_one('[data-hook="review-body"]')
body = body_el.get_text(strip=True) if body_el else ""
# 投稿者名
author_el = div.select_one('span.a-profile-name')
author = author_el.get_text(strip=True) if author_el else ""
# 日付と国
date_el = div.select_one('[data-hook="review-date"]')
date_text = date_el.get_text(strip=True) if date_el else ""
# 例: "Reviewed in the United States on January 15, 2025"
country_match = re.search(r'Reviewed in (.+?) on', date_text)
date_match = re.search(r'on (.+)$', date_text)
country = country_match.group(1) if country_match else ""
date = date_match.group(1) if date_match else ""
# Verified Purchase
verified_el = div.select_one('[data-hook="avp-badge"]')
verified = bool(verified_el)
reviews.append({
"author": author,
"rating": rating,
"title": title,
"content": body,
"date": date,
"country": country,
"verified": verified,
})
return reviews
私はこのセレクターセットを複数のASINで数か月動かしていますが、data-hook 属性は一度も変わっていません。一方でCSSクラスの方は、その期間に少なくとも2回は変わりました。
ステップ4:ページネーションとAmazonの10ページ制限に対処する
Amazonでは pageNumber パラメータが、10ページ × 各10件、つまりフィルターの組み合わせごとに最大約100件までという厳しい上限になっています。10ページ目以降は「次へ」ボタン自体が消えます。
基本のページネーションループは次の通りです。
all_reviews = []
for page in range(1, 11):
url = f"https://www.amazon.com/product-reviews/{asin}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber={page}"
soup = get_soup(session, url)
page_reviews = extract_reviews(soup)
if not page_reviews:
break # このページにはもうレビューがない
all_reviews.extend(page_reviews)
print(f"Page {page}: {len(page_reviews)} reviews")
10ページ以上のAmazonレビューを取る方法
回避策はフィルターの分割です。filterByStar と sortBy の組み合わせごとに、独立した10ページ枠が与えられます。
星フィルターの値: one_star、two_star、three_star、four_star、five_star
並び替えの値: recent、helpful(デフォルト)
5種類の星フィルター × 2種類の並び替えを組み合わせれば、商品ごとに最大100ページ、1,000件のレビューにアクセスできます。星の分布が偏っている商品なら、実際にはほぼ全件に近いレビューを取れることも少なくありません。
star_filters = ["one_star", "two_star", "three_star", "four_star", "five_star"]
sort_orders = ["recent", "helpful"]
all_reviews = []
seen_titles = set() # 簡易的な重複排除
for star in star_filters:
for sort in sort_orders:
for page in range(1, 11):
url = (
f"https://www.amazon.com/product-reviews/{asin}"
f"?filterByStar={star}&sortBy={sort}&pageNumber={page}"
)
soup = get_soup(session, url)
page_reviews = extract_reviews(soup)
if not page_reviews:
break
for review in page_reviews:
# タイトル + 投稿者名で重複排除
key = (review["title"], review["author"])
if key not in seen_titles:
seen_titles.add(key)
all_reviews.append(review)
print(f"[{star}/{sort}] Page {page}: {len(page_reviews)} reviews")
print(f"Total unique reviews: {len(all_reviews)}")
バケット同士には重なりが出るので、重複排除は必須です。私はレビュータイトル + 投稿者名の組み合わせを簡易キーとして使っています。完璧ではありませんが、ほとんどの重複はこれで弾けます。
ステップ5:ボット対策をかわす(ローテーション、間隔、リトライ)
Amazonは AWS WAF Bot Control を使っており、かなり攻撃的になっています。User-Agentを回すだけ、遅延を入れるだけ、のような単一対策ではもはや十分ではありません。
| 手法 | 実装方法 |
|---|---|
| User-Agentのローテーション | 10種類以上の実ブラウザ文字列からランダム選択 |
| 指数バックオフ | 503時に 2秒 → 4秒 → 8秒 と待機 |
| リクエスト間隔の調整 | ページ間で random.uniform(2, 5) 秒待つ |
| プロキシのローテーション | 住宅系プロキシを順番に切り替える |
| セッションフィンガープリント | セッションごとにCookieとヘッダーを固定する |
| TLSのなりすまし | 本番では標準の requests ではなく curl_cffi を使う |
本番運用向けのリトライラッパーは次のようになります。
import time, random
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 15_7_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
]
def scrape_with_retries(session, url, max_retries=3):
for attempt in range(max_retries):
try:
session.headers["User-Agent"] = random.choice(USER_AGENTS)
time.sleep(random.uniform(2, 5))
response = session.get(url, timeout=15)
# ブロック検知
if "validateCaptcha" in response.url or "Robot Check" in response.text:
wait = (2 ** attempt) * 5
print(f"CAPTCHAを検知しました。{wait}秒待機します...")
time.sleep(wait)
continue
if response.status_code in (429, 503):
wait = (2 ** attempt) * 2
print(f"レート制限を受けました ({response.status_code})。{wait}秒待機します...")
time.sleep(wait)
continue
if "ap_email" in response.text:
raise Exception("ログイン壁 — Cookieの期限が切れています")
return BeautifulSoup(response.text, "lxml")
except Exception as e:
if attempt == max_retries - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}")
return None
プロキシについて一言。Amazonは既知のデータセンターIP帯(AWS、GCP、Azure、DigitalOceanなど)をネットワーク層でブロックしています 。数百ページ以上をスクレイピングするなら、住宅系プロキシはほぼ必須で、規模にもよりますが月50〜200ドル以上は見ておくべきです。小規模(1日100リクエスト未満)なら、自宅回線から慎重に間隔を空けて送るだけでもうまくいくことがあります。
AmazonはTLSフィンガープリントも確認します。Python標準の requests ライブラリは、WAFに事前ブロックされやすい既知のJA3ハッシュを持っています 。本番用途では、実ブラウザのTLSスタックを模倣できる curl_cffi の使用を検討してください。チュートリアル規模(数百ページ程度)なら、適切なヘッダーを付けた requests でもたいてい十分です。
ステップ6:取得したAmazonレビューをCSVまたはExcelに出力する
レビューを取得したら、pandas を使って使いやすい形式にまとめるのは簡単です。
import pandas as pd
df = pd.DataFrame(all_reviews)
df.to_csv("amazon_reviews.csv", index=False)
print(f"Exported {len(df)} reviews to amazon_reviews.csv")
出力例:
| author | rating | title | content | date | country | verified |
|---|---|---|---|---|---|---|
| Sarah M. | 5.0 | 今年いちばんの買い物 | バッテリーが1日持つし、画面もとてもきれい... | January 15, 2025 | the United States | True |
| Mike T. | 2.0 | 2週間でがっかり | 充電ポートが動かなくなった... | February 3, 2025 | the United States | True |
| Priya K. | 4.0 | 値段以上の価値 | 必要なことはすべてできるけれど、重いアプリでは少しもたつく... | March 10, 2025 | the United States | False |
Excelに出すなら: df.to_excel("amazon_reviews.xlsx", index=False)(openpyxl が必要です)。
Google Sheets に出す場合は gspread が使えますが、Google Cloud の設定が8ステップ以上必要です。プロジェクト作成、2つのAPIの有効化、サービスアカウント資格情報の生成、シート共有などが発生します。もし「スクレイピング本体より設定の方が大変では?」と感じるなら、その感覚は正しいです。(こういうときこそ、Thunderbit のようにワンクリックでGoogle Sheetsへ出力できるツールが魅力的に見えてきます。)
おまけ:たった5行でスクレイピング結果に感情分析を加える
多くのスクレイピング解説はCSV出力で終わります。でも、感情スコアを付けることで、単なるデータが意思決定材料に変わります。
最も手軽なベースラインは TextBlob です。
from textblob import TextBlob
df["sentiment"] = df["content"].apply(lambda x: TextBlob(str(x)).sentiment.polarity)
これで各レビューに -1.0(非常にネガティブ)から +1.0(非常にポジティブ)までのスコアが付きます。出力例:
| content(抜粋) | rating | sentiment |
|---|---|---|
| "Battery lasts all day, screen is gorgeous..." | 5.0 | 0.65 |
| "The charging port stopped working after..." | 2.0 | -0.40 |
| "Does everything I need, minor lag on..." | 4.0 | 0.25 |
| "Absolute garbage. Returned immediately." | 1.0 | -0.75 |
| "It's okay. Nothing special but works." | 3.0 | 0.10 |
面白いのは、星評価と文章のニュアンスがズレている行です。たとえば3星なのに文章はかなり好意的、あるいは5星なのに言い回しがネガティブ、といったケースです。こうしたズレは、星だけでは見えない細かな本音を示してくれます。

本番レベルの精度を求めるなら、Hugging Face Transformers をおすすめします。VADERはツイート向けに学習されていて、商品レビュー向けではないですし、Transformerモデルはレキシコン系ツールよりレビュー分類で98%以上の精度を出すとされています。nlptown/bert-base-multilingual-uncased-sentiment モデルなら、1〜5星を直接予測することもできます。
from transformers import pipeline
clf = pipeline("sentiment-analysis",
model="nlptown/bert-base-multilingual-uncased-sentiment")
df["predicted_stars"] = df["content"].apply(
lambda x: int(clf(str(x)[:512])[0]["label"][0])
)
AmazonレビューはJ字型分布を示します。5星に大きな山、1星に小さめの山、その間は谷になりやすいのです。つまり、平均星評価は実際の品質を測る指標としてはあまり当てになりません。1星群を分けて共通点を探すと、たいていそこに修正可能な欠陥が潜んでいます。
本音の比較:自作Python vs 有料スクレイピングAPI vs Thunderbit
私はAmazon用のPythonスクレイパーを何本も保守してきましたが、正直に言うと、壊れます。セレクターは変わり、Cookieは切れ、Amazonは新しいボット検知を導入し、気づけば土曜の朝がデータ分析ではなくスクレイパーのデバッグで終わります。フォーラムでも同じ不満が多く、「先月は動いていた」スクリプトが、今は頻繁な修正なしでは使えないという声が目立ちます。
3つの主要アプローチを比べるとこうなります。
| 比較項目 | 自作Python(BS4/Selenium) | 有料スクレイピングAPI | Thunderbit(ノーコード) |
|---|---|---|---|
| 初期設定時間 | 1〜3時間 | 30分(APIキーのみ) | 2分 |
| コスト | 無料(+プロキシ費用) | 月50〜200ドル以上 | 無料枠あり |
| ログイン壁対応 | Cookieを手動管理 | たいてい対応済み | 自動対応 |
| 保守工数 | 高い(セレクターが壊れる) | 低い(提供側が保守) | ほぼゼロ(AIが適応) |
| ページネーション | 自作コードが必要 | 標準機能 | 標準機能 |
| 多国対応 | ドメインごとに別セッション | たいてい対応 | ブラウザベースなのでロケールに準拠 |
| 感情分析 | 自分で実装 | 場合によって含まれる | Sheetsへ出して自由に分析可能 |
| 向いている用途 | 学習、完全な制御が必要な場合 | スケール運用、本番パイプライン | すぐ欲しいデータ、非開発チーム |
Pythonは自由度が高く、Webスクレイピングの仕組みを内部から学ぶには最良の方法です。課金API(ScrapingBee、Oxylabs、Bright Data など)は、コストより稼働率が重要な本番パイプラインに向いています。そして、開発工数をかけずにレビュー情報が必要なチーム、たとえば競合商品の動向を毎週追うEC運用や、広告コピー用の顧客の言葉を集めたいマーケティングチームには、もうひとつ別の選択肢があります。
ThunderbitでAmazonレビューを取得する方法(ノーコード、保守不要)
私たちは、Pythonスクレイパーを保守し続けるのが大げさに感じられる場面のためにThunderbitを作りました。使い方は次の通りです。
- Thunderbit Chrome拡張をインストールする
- ブラウザでAmazonの商品レビューページを開く(すでにログインしているので、ログイン壁は気になりません)
- 「AI Suggest Fields」 をクリックする — Thunderbit がページを読み取り、Author、Rating、Title、Review Text、Date、Verified Purchase などの列を提案します
- 「Scrape」 をクリックする — ページネーション込みで即座にデータを抽出します
- Excel、Google Sheets、Airtable、Notion にエクスポートする
最大の利点は、ThunderbitのAIが毎回その時点のページ構造を読み直すことです。CSSセレクターの保守も、Cookie管理も、ボット対策コードも不要です。AmazonがHTMLを変えても、AIが追従します。プログラム的に使いたいが完全自作は避けたい人向けには、Extract API もあります。これはAIによる項目検出つきの構造化データ抽出APIで、セレクター保守は不要です。
Amazonデータをさらに深掘りしたい方は、Amazon商品とレビューのスクレイピング方法 や Amazon売上データの抽出と分析 もご覧ください。
PythonでAmazonレビューを大規模に取得するコツ
複数のASINにまたがってレビューを取得するなら、次の工夫でトラブルをかなり減らせます。
- ASINごとにまとめて処理し、商品間にも待機時間を入れる。 ページ間だけでなく、商品間でも間隔を空けましょう。私はASINごとに10〜15秒の休止を入れています。
- 重複排除は厳しめに行う。 複数の星フィルターや並び替え条件を組み合わせると、同じレビューが重複します。
(title, author, date)のタプルをキーにすると便利です。 - 失敗を記録する。 どのASIN+ページ+フィルターの組み合わせが失敗したかを残しておけば、全体を取り直さずに再試行できます。
- 大規模案件ではDBに保存する。 CSVを増やし続けるより、SQLiteのような軽量DBのほうがはるかに扱いやすいです。
import sqlite3
conn = sqlite3.connect("reviews.db")
df.to_sql("reviews", conn, if_exists="append", index=False)
- 定期実行を組む。 継続的な監視なら、cronジョブを設定するか、Thunderbitの Scheduled Scraper 機能を使いましょう。URLとスケジュールを指定するだけで、サーバーなしで自動実行できます。
他の方法も知りたい方は、おすすめの自動Webスクレイピングツール や WebサイトからExcelへデータを取得する方法 も参考になります。
法律と倫理に関する簡単な注意
Amazonの利用条件では、「ロボット、スパイダー、スクレイパー、その他の自動手段を使ってAmazonサービスへアクセスすること」を明確に禁じています。一方で、近年の米国判例では、公開データのスクレイピングに有利な判断も出ています。Meta Platforms v. Bright Data(2024年1月) では、連邦裁判所が、ログインしていない「ユーザー」ではないスクレイパーによる公開データの取得は利用規約違反に当たらないと判断しました。
ただし重要なのは、ログイン後の取得(このチュートリアルが扱っている部分)では契約法の領域に入ることです。Amazonアカウントを作成した時点で利用規約に同意しているからです。公開表示されている目玉レビューを取得する方が、ログイン壁の向こう側を取得するよりも法的リスクは低くなります。
実務上のガイドラインとしては、取得データを商用で再配布しない、公開表示されている範囲を超える個人データを取らない、robots.txt を尊重する、大規模利用や商用利用では法務に相談する、という点が重要です。これは法的助言ではありません。法的な論点をさらに知りたい方は、Webスクレイピングの法的影響 の解説もご覧ください。
まとめ:PythonでAmazonレビューを取得するか、コード自体をやめるか
このガイドで扱った内容を振り返ると、次の通りです。
- ログイン壁は実在するが、Cookieベース認証で突破できる — ブラウザから7つのCookieをコピーし、
requests.Session()に入れる - 抽出にはCSSクラスではなく
data-hookセレクターを使う — 数週間ごとに壊れるのを避けられる - 星フィルターと並び替えを組み合わせて10ページ制限を回避し、商品ごとに500件以上のレビューへアクセスする
- TextBlobで簡易的に感情分析を追加するか、Hugging Face Transformers で本番精度を狙う
- ボット対策として、間隔調整、User-Agentローテーション、指数バックオフ、住宅系プロキシを維持する
Pythonは完全な自由度を与えてくれますし、仕組みを内部から理解するには最適です。ただし、やりたいことが「本番用データパイプラインを組みたい」ではなく「金曜日までに競合レビューをスプレッドシートに入れたい」なのであれば、自作スクレイパーの保守負担は見合わないかもしれません。
Thunderbit なら、認証、セレクター、ページネーション、エクスポートまでクリックだけで完結します。無料枠 を試して、あなたのワークフローに合うか確認してみてください。Amazonがボット対策をさらに強化するにつれて、リアルタイムで適応するAIツールは「あれば便利」ではなく「必要なもの」になっていくはずです。
スクレイピングの手順を動画で見たい方は、Thunderbit YouTube チャンネル もぜひご覧ください。
FAQ
1. ログインせずにAmazonレビューは取得できますか?
はい、ただし商品詳細ページ(/dp/{ASIN}/)に表示される約8件の「目玉レビュー」だけです。並び替え、絞り込み、ページネーションがある全文レビューは、2024年後半時点で認証が必要です。多くの業務用途では、ログイン壁への対応が必要になります。
2. Amazonレビューをスクレイピングするのは合法ですか?
Amazonの利用規約では自動スクレイピングが禁止されています。ただし、米国の最近の判例(Meta v. Bright Data、2024年、hiQ v. LinkedIn)は、公開アクセス可能なデータのスクレイピングを支持する傾向があります。ログイン後の取得は、Amazonの利用規約に同意しているため、法的リスクが高くなります。商用利用では法務に相談してください。
3. 1商品あたり何件のAmazonレビューを取得できますか?
Amazonは、並び替えと星フィルターの組み合わせごとにレビュー表示を10ページまでに制限しています。5種類の星フィルター × 2種類の並び替えを使うと、1商品あたり最大100ページ(おおむね1,000件)までアクセスできます。キーワードフィルターを使えば理論上はもっと増えますが、重複もかなり多くなります。
4. Amazonレビューのスクレイピングに最適なPythonライブラリは何ですか?
静的HTMLの解析なら、requests + BeautifulSoup の組み合わせが最も一般的で安定しています。JavaScriptの描画が必要な場合は Selenium が役立ちます。ログイン壁やページネーションを自動で処理したいノーコード代替案としては、Thunderbit を試してみてください。
5. Amazonスクレイピングでブロックされない方法は?
10種類以上の実ブラウザ由来のUser-Agentをローテーションする、リクエスト間に2〜5秒のランダム遅延を入れる、503/429エラーでは指数バックオフを行う、スケールするなら住宅系プロキシを使う(データセンターIPは事前ブロックされやすい)、そしてリクエスト間でセッションCookieを一貫させる、という方法があります。保守不要で進めたいなら、Thunderbit がブラウザセッション経由でボット対策を自動処理します。
さらに詳しく


