PythonでAmazonレビューをスクレイピングする方法:ログイン壁の突破から感情分析まで

最終更新日 August 21, 2026
PythonでAmazonレビューをスクレイピングする方法:ログイン壁の突破から感情分析まで
AI要約

Amazonは2025年後半にレビュー全文ページをログイン必須にし、多くのPythonスクレイパーが停止しました。本記事では、Cookieベース認証でログイン壁を突破する方法、data-hook を使った安定したレビュー抽出、10ページ制限を回避するためのフィルタ分割、ボット対策、CSV/Excel出力、TextBlobやTransformerによる感情分析までを実践的に解説します。最後に、コード保守が不要なThunderbitで同じ作業を短時間で行う方法も紹介します。

私のAmazonレビュー用スクレイパーは6週間、何の問題もなく動いていました。ところがある朝、返ってきたのは 200 OK と、真っ白なページだけ。エラーはなし、CAPTCHAもなし。何百件ものレビューが表示されていたはずの場所に、空っぽのHTMLがあるだけでした。

もし心当たりがあるなら、あなただけではありません。2025年後半、Amazonはレビュー全文ページをログイン必須に変更し、多くのPythonスクレイピングスクリプトが一夜にして動かなくなりました。ここ数か月、Thunderbit でAIスクレイパーの開発と自分のPythonレビュー取得パイプラインの保守の両方に取り組んできたので、最初にスクリプトが止まったときに欲しかったガイドを、今こそ書こうと思いました。この記事では、実際に使える手法をまとめます。Cookieベースの認証、AmazonのCSS難読化を乗り越える安定したセレクタ、10ページ制限を回避する方法、ボット対策、さらに生のレビュー文を実際のビジネスインサイトに変える感情分析まで解説します。途中で「このコードを全部、自分で保守したくない」と思ったら、同じ作業をPythonなしで約2分でこなす Thunderbit の使い方も紹介します。

Amazonレビューのスクレイピングとは?なぜ重要なのか?

Amazonレビューのスクレイピングとは、星評価、レビュー本文、投稿者名、日付、購入済みバッジなどの顧客レビュー情報を、Amazonの商品ページからプログラムで抽出することです。Amazonは2010年にProduct Advertising APIからレビュー情報を削除し、その後も復活させていないため、このデータをプログラムで取得する手段はWebスクレイピングしかありません。

数字を見ても、その価値は明らかです。購入前にレビューを読む人は95% にのぼり、94%がAmazonを商品レビューの第一情報源に挙げています。商品ページにレビューを5件表示するだけで、コンバージョン率が270%上がることもあります。レビュー感情を体系的に分析している企業では、顧客維持率が最大15%向上 した例もあります。これは抽象的なデータサイエンスではなく、競合分析、製品改善のヒント、マーケティングに使える言葉そのものが、Amazonのサーバー上にそのまま載っているという話です。

なぜPythonでAmazonレビューをスクレイピングするのか

この用途では、いまもPythonが最有力です。Pythonは2024年のStack Overflow Developer Surveyで最も欲しい言語第1位 であり、requests、BeautifulSoup、pandas、Scrapy といったエコシステムのおかげで、専業開発者でなくてもWebスクレイピングに取り組みやすいからです。

チームごとに、このデータの活かし方は少しずつ異なります。

チーム活用シーン抽出する情報
プロダクト / R&D繰り返し出る不満を見つけ、改善の優先順位を決める星1〜2のレビュー本文、キーワード頻度
営業競合商品の評判を把握する評価、レビュー件数の推移
マーケティング広告コピーに使える顧客の言い回しを拾うポジティブな表現、機能への言及
EC運用自社商品の評価推移を追う星の分布、購入済み比率
市場調査カテゴリ内の主要製品を機能面で比較する複数ASINのレビューセット

あるキッチン用品ブランドはネガティブレビューを分析し、22%が「ノンスティック加工が剥がれる」と指摘している ことを発見しました。そこで製品を改良し、60日以内に再びAmazonのベストセラー1位を奪還しました。フィットネストラッカー企業では、レビュー文から「バンドが肌に合わない」という声 を拾い、ラテックスアレルギーの課題を特定。低刺激版を投入し、返品率を40%削減しました。こうした成果があるからこそ、エンジニアリングの手間に見合うのです。

ログイン壁:なぜAmazonレビュー用スクレイパーは動かなくなったのか

2024年11月14日、Amazonは商品レビュー全文ページの閲覧にサインインを必須化しました。この変更はコミュニティフォーラムスクレイピングベンダーのブログ でも確認されています。シークレットウィンドウで /product-reviews/{ASIN}/ にアクセスすると、レビューの代わりにサインインページへリダイレクトされます。

python-web-scraping-diagram.webp

症状はかなり見えにくいです。スクリプトは 200 OK を受け取るのに、HTML本文にはレビューではなくログインフォーム(name="email"id="ap_password")が入っているだけ。エラーコードも、CAPTCHAもありません。ただ……使える情報が何もないのです。

これはAmazonが、ボット対策と地域ごとのコンプライアンス対応のために行っているものです。適用は一貫しておらず、特に1ページ目では、最初の数件だけ見えてから壁が出ることもありますが、規模を持って動かすスクレイパーなら、常にログイン壁がある前提で考えるべきです。

Amazonの各国ドメイン(.de.co.uk.co.jp など)は、それぞれ独立してこの壁を適用します。あるフォーラムユーザーは「国ごとにログインが必要」と表現していました。.com のCookieは .co.uk では使えません。

Featured Reviews と Full Reviews の違い:ログインなしで今も見られるもの

Amazonの商品ページ(/dp/{ASIN}/)では、認証なしでもおよそ8件の「featured reviews」 が表示されます。これは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文字のIDです。商品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を抽出する方法

  1. Chromeで amazon.com にログインする
  2. DevTools を開く(F12 または右クリック → 検証)
  3. ApplicationStorageCookieshttps://www.amazon.com に移動する
  4. 表の各Cookie名を見つけて値をコピーする
  5. 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")

ちょっとしたコツとして、レビューページへ直接行く前に、先に商品ページを開いてください。これで、より自然なブラウジングの流れを作れます。

# まず商品ページにアクセスする(実際の閲覧に近づける)
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(地域依存)
購入済み表示[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_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 パラメータを、1ページ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レビューを取る方法

回避策はフィルタの分割です。filterByStarsortBy の組み合わせごとに、独立した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 + 1} 回目が失敗しました: {e}")

    return None

プロキシについて一言。Amazonは既知のデータセンターIP帯(AWS、GCP、Azure、DigitalOcean)をネットワーク層でブラックリスト化しています 。数百ページ以上をスクレイピングするなら、住宅用プロキシは事実上必須です。量にもよりますが、月額50〜200ドル以上は見込んでください。小規模プロジェクト(1日100リクエスト未満)なら、自宅IPから丁寧に間隔を空けて実行するだけでも十分なことが多いです。

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"{len(df)}件のレビューを amazon_reviews.csv に出力しました")

出力例:

authorratingtitlecontentdatecountryverified
Sarah M.5.0今年一番の買い物バッテリーが一日持つし、画面が本当にきれい...January 15, 2025the United StatesTrue
Mike T.2.02週間でがっかり充電ポートが動かなくなった...February 3, 2025the United StatesTrue
Priya K.4.0価格に対してかなり良い必要な機能は全部そろっていて、重いアプリでは少し遅いけど...March 10, 2025the United StatesFalse

Excelに出力するなら df.to_excel("amazon_reviews.xlsx", index=False) を使います(openpyxl が必要です)。

Google Sheets なら gspread ライブラリがありますが、Google Cloudの設定だけで8ステップ以上 かかります。プロジェクト作成、2つのAPI有効化、サービスアカウント資格情報の発行、シート共有……。これがスクレイピング本体より大変に感じるなら、その感覚は正しいです。(こういう場面で、Thunderbit のワンクリックGoogle Sheets出力がかなり魅力的に見えてきます。)

おまけ:5行のPythonでレビューに感情分析を追加する

多くのスクレイピングチュートリアルはCSV出力で終わります。でも、感情スコアを付けてこそ、生データがビジネス判断に変わります。

最速のベースラインは TextBlob です。

from textblob import TextBlob

df["sentiment"] = df["content"].apply(lambda x: TextBlob(str(x)).sentiment.polarity)

これで各レビューに対して、-1.0(かなりネガティブ)から +1.0(かなりポジティブ)までの極性スコアが得られます。出力例:

content(抜粋)ratingsentiment
"Battery lasts all day, screen is gorgeous..."5.00.65
"The charging port stopped working after..."2.0-0.40
"Does everything I need, minor lag on..."4.00.25
"Absolute garbage. Returned immediately."1.0-0.75
"It's okay. Nothing special but works."3.00.10

面白いのは、不一致の行です。たとえば、星3つなのに文章はポジティブ、あるいは星5つなのに言葉はネガティブといったケースです。こうしたズレには、星評価だけでは見えない、微妙な顧客意見が隠れていることがよくあります。

ai-review-analysis.webp

本番レベルの精度を求めるなら、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つの集団を切り出して、繰り返し出てくるテーマを探してください。たいてい、1つの修正可能な欠陥がそこに隠れています。

正直なトレードオフ:Python自作 vs. 有料スクレイピングAPI vs. Thunderbit

私はAmazon向けのPythonスクレイパーを保守してきましたが、正直に言うと、壊れます。セレクタは変わるし、Cookieは切れるし、Amazonは新しいボット検知を導入し、気づけば土曜の朝がデータ分析ではなくスクレイパーのデバッグに消えます。フォーラムでも同じ不満が報告されています。先月は動いていたDIYスクリプトが、今は継ぎはぎ修正なしでは使えない、という声です。

3つの主要な選択肢を比較するとこんな感じです。

比較項目DIY Python(BS4/Selenium)有料スクレイピングAPIThunderbit(ノーコード)
初期設定時間1〜3時間30分(APIキー取得)2分
コスト無料(+プロキシ費用)月額50〜200ドル以上無料プランあり
ログイン壁対応手動でCookie管理たいてい対応済み自動対応
保守負担高い(セレクタが壊れる)低い(提供側が保守)ほぼゼロ(AIが適応)
ページ送り自作コードが必要標準搭載標準搭載
複数国対応ドメインごとに別セッションたいてい対応ブラウザベースなのでロケール準拠
感情分析自分で実装含まれることもあるSheetsに出して自由に分析
向いている用途学習、完全な制御本番パイプラインすぐ欲しいデータ、非開発チーム

Pythonは完全な制御ができ、Webスクレイピングの仕組みを深く理解するには最適です。有料API(ScrapingBee、Oxylabs、Bright Data など)は、コストよりも稼働率が重要な本番用途に向いています。そして、開発工数なしでレビューデータが必要なチーム、たとえば競合商品のレビューを毎週見るEC運用や、広告コピー用の顧客表現を拾いたいマーケティングチームには、もう1つの道があります。

ThunderbitでAmazonレビューをスクレイピングする方法(コード不要、保守不要)

私たちは、Pythonスクレイパーの保守が大げさに感じられるケースにぴったり合うように Thunderbit を作りました。流れはこんな感じです。

  1. Thunderbit Chrome拡張機能 をインストールする
  2. ブラウザでAmazonの商品レビューページを開く(すでにログイン済みなので、ログイン壁は問題になりません)
  3. 「AI Suggest Fields」 をクリックする — Thunderbitがページを読み取り、Author、Rating、Title、Review Text、Date、Verified Purchase などの列を提案します
  4. 「Scrape」 をクリックする — 組み込みのページ送り付きで、すぐにデータを抽出します
  5. Excel、Google Sheets、Airtable、Notion にエクスポートする

最大の利点は、ThunderbitのAIが毎回ページ構造を読み直すことです。CSSセレクタの保守も、Cookie管理も、ボット対策コードも必要ありません。AmazonがHTMLを変えても、AIが追従します。プログラムからのアクセスは欲しいけれど完全な自作は避けたい、という人向けには、Thunderbit の Extract API もあります。AIによる項目検出付きの構造化データ抽出をAPIで実行でき、セレクタの保守は不要です。

Amazonデータをさらに深掘りしたい方は、Amazon商品とレビューのスクレイピング方法 や、Amazonの売上データを抽出・分析する方法 も参考にしてください。

PythonでAmazonレビューを大規模にスクレイピングする際のコツ

複数のASINにまたがってレビューを取るなら、次の習慣でかなり楽になります。

  • ASINごとにまとめて処理し、商品間にも間隔を空ける。 ページ間だけでなく、商品間にも待機を入れてください。私はASIN間で10〜15秒の休止を入れています。
  • 徹底的に重複排除する。 複数の星フィルタやソート条件を組み合わせると、レビューは重複します。(title, author, date) のタプルを重複排除キーに使うと便利です。
  • 失敗をログに残す。 どのASIN + ページ + フィルタ組み合わせで失敗したかを記録しておけば、全体を取り直さずに再試行できます。
  • 大規模案件ではデータベースに保存する。 CSVを増やし続けるより、シンプルなSQLiteの方がずっと扱いやすいです。
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のToSへ同意しているからです。公開表示されているfeatured reviewsを取るより、ログイン壁の内側をスクレイピングする方が法的リスクは高くなります。

実務上の指針としては、取得したデータを商用で再配布しない、公開表示されている以上の個人データを取らない、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チャンネル もチェックしてください。

よくある質問

1. Amazonレビューはログインなしでスクレイピングできますか?

はい、ただし商品詳細ページ(/dp/{ASIN}/)に表示される約8件の「featured reviews」だけです。並び替え、フィルタ、ページ送り付きの全文レビューは、2024年後半以降、認証が必要です。多くの業務用途では、ログイン壁への対応が必要になります。

2. Amazonレビューをスクレイピングするのは合法ですか?

Amazonの利用規約では自動スクレイピングが禁じられています。ただし、近年の米国判例(Meta v. Bright Data, 2024; hiQ v. LinkedIn)は、公開アクセス可能なデータのスクレイピングを支持しています。ログイン後のスクレイピングは、AmazonのToSに同意済みであるため法的リスクが高くなります。商用利用では弁護士に相談してください。

3. Amazonレビューは1商品あたり何件までスクレイプできますか?

Amazonは、ソート順と星フィルタの組み合わせごとにレビューを10ページまでに制限しています。5つの星フィルタ × 2つのソート順を使うと、商品ごとに最大100ページ(およそ1,000件)にアクセスできます。キーワードフィルタを使えば理論上の上限はもっと高くなりますが、重複もかなり増えます。

4. Amazonレビューのスクレイピングに最適なPythonライブラリは?

静的HTMLの解析には requests + BeautifulSoup の組み合わせが、最も一般的で信頼性も高いです。JavaScriptのレンダリングが必要な場合は Selenium が便利です。ログイン壁やページ送りを自動処理できるノーコード代替としては、Thunderbit を試してみてください。

5. Amazonスクレイピングでブロックされないようにするには?

10種類以上の実在ブラウザ文字列からUser-Agentをローテーションし、リクエスト間に2〜5秒のランダム遅延を入れ、429/503エラー時には指数バックオフを実装し、規模が大きい場合は住宅用プロキシを使い(データセンターIPは事前にブロックされがちです)、リクエスト間でセッションCookieを一貫させてください。保守不要で進めたいなら、Thunderbit がブラウザセッション経由でボット対策を自動処理します。

さらに学ぶ

Fawad Khan
Fawad Khan
Fawadは文章を書くことを仕事にしていて、正直なところ、かなりそれが好きです。長年にわたって、どんなコピーが人の記憶に残り、どんなコピーが読み飛ばされるのかを探ってきました。マーケティングについて聞けば、何時間でも話し続けます。カルボナーラについて聞けば、もっと長く話します。
目次
Thunderbit · AIウェブデータエージェント

1クリックであらゆるページからデータを抽出

25万人以上のユーザーに支持されています
無料プランあり
Webページからスプレッドシートへ
欲しい内容を伝えるだけ — ThunderbitのAIエージェントが取得し、Excel、Google Sheets、Airtable、Notionへ出力します。すぐに無料で始められます。
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week