PythonでAmazon製品データを大規模にスクレイピングする方法

3行のBeautifulSoupチュートリアルは一度だけ動作し、その後AmazonはCAPTCHAを出してきます。実際に大規模で壊れるのは、価格セレクタの変化、地理的価格設定、IPブロックであり、それを乗り越えるパイプラインです。

Amazon製品データのスクレイピングは、初心者向けチュートリアルでは簡単に見えます:requests、BeautifulSoup、タイトルと価格を取得して完了。それは数百回実行するまで正確に機能し、その時点でAmazonはロボットチェックページを出し、価格セレクタはNoneを返します。このガイドは、実際のサイトとの接触に耐えるバージョンについてです—ASINを最初にするパイプライン、実際に壊れるセレクタ、同じ製品が異なるIPに異なる価格を示す理由、そしてCAPTCHAの壁を避けるプロキシ設定についてです。それは公開されている製品データ(タイトル、価格、評価、在庫状況)についてであり、ログインの背後にあるものではありません。

URL構造:ASINが鍵

すべてのAmazon製品にはASINがあります—B08N5WRWNWのような10文字の識別子で、カタログ全体がそれに基づいています。製品ページは単にhttps://www.amazon.com/dp/<ASIN>であり、同じASINは市場をまたいでマッピングされます(amazon.co.uk/dp/<ASIN>amazon.de/dp/<ASIN>)。検索とカテゴリページは/s?の下にクエリとブラウズノードパラメータと共に存在します。したがって、スケーラブルなパイプラインは2つのステージを持ちます:検索またはベストセラーページからASINを発見し、それぞれをその/dp/ページからハイドレートします。1つの注意点—「親」ASIN(サイズや色のバリエーションを持つ製品)は自動選択された子バリエーションに解決されるので、実際に到達したバリエーションASINをキャプチャします。

import requests
from bs4 import BeautifulSoup

PROXY = "http://USER:PASS@gate.quantumproxies.io:8000"
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
           "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
           "Accept-Language": "en-US,en;q=0.9"}

def product(asin, domain="com"):
    url = f"https://www.amazon.{domain}/dp/{asin}"
    r = requests.get(url, headers=HEADERS,
                     proxies={"http": PROXY, "https": PROXY}, timeout=20)
    soup = BeautifulSoup(r.text, "html.parser")
    return parse(soup, asin)

誰もがコピーしたセレクタとAmazonが廃止したもの

ほぼすべての古いチュートリアルはspan#priceblock_ourpriceから価格を読み取ります。Amazonは複数の価格ブロックレイアウトを提供し、A/Bテストを行っているため、その単一のIDは今日ほとんどのページで空です。耐久性のあるアプローチは、既知の価格コンテナを順番に試し、最初に一致するものを取ることです—そして、価格がないことをクラッシュではなく実際の状態(通常は在庫切れ)として扱うことです。

def parse(soup, asin):
    title = soup.select_one("#productTitle")
    price = None
    for sel in ["span.a-price span.a-offscreen",   # current layout
                "#priceblock_ourprice",             # legacy
                "#priceblock_dealprice",            # deal layout
                "#corePrice_feature_div .a-offscreen"]:
        el = soup.select_one(sel)
        if el and el.get_text(strip=True):
            price = el.get_text(strip=True)
            break
    rating = soup.select_one("span.a-icon-alt")
    return {
        "asin": asin,
        "title": title.get_text(strip=True) if title else None,
        "price": price,                 # None -> likely out of stock
        "rating": rating.get_text(strip=True) if rating else None,
    }
ASINを最初にするAmazonスクレイピングパイプラインの図:検索ページがASINを発見し、住宅プロキシが配信地理を設定し、製品ページが詳細を提供し、CSVに出力
検索からASINを発見し、それぞれをその/dp/ページからハイドレートし、価格を取得したい市場に出口IPを固定します。

同じ製品が2つの価格を示す理由

これは価格データセットを静かに台無しにする事実です。Amazonは価格と在庫状況を購入者の配送先にローカライズします—「配送先」設定—これは主にIPから推測されます。ドイツのデータセンターIPからamazon.comをスクレイピングすると、ユーロ価格、異なるオファー、または米国の購入者が見るものとは異なるBuy Boxの勝者を得ることがあります。競争価格データを収集している場合、出口IPの地理は実験そのものです:米国の購入者が見る価格をキャプチャするには、米国の住宅プロキシを経由します;英国市場には英国の出口を使用します。1つの製品、複数の価格、サンプルする市場ごとに1つ。

地理ターゲットの住宅プロキシを取得する

なぜ素朴なスクレイパーがブロックされるのか

Amazonは自動化されたリクエスト管理システムを運用しています:1つのIPから急速にバーストすると、CAPTCHA、IP禁止、または簡略化されたページを受け取ります。3つのことが大量のスクレイパーを生かします。まず、IPを回転させ、1つのアドレスが全負荷を担わないようにします—回転する住宅プールは多くの実際の消費者IPにリクエストを分散します。次に、ペースを調整します:ランダムな遅延と同時実行制限、フラットアウトループではありません。第三に、整合性のあるヘッダーを送信します—実際のブラウザのUser-AgentとAccept-Language、デフォルトのPython文字列ではありません。ページが疑わしいほど短く返ってきたり、ロボットチェックマーカーを含んでいる場合、それを破棄し、新しいIPで再試行します。

import time, random

def fetch_many(asins, domain="com"):
    rows = []
    for asin in asins:
        for attempt in range(3):
            data = product(asin, domain)
            if data["title"]:            # got a real page
                rows.append(data)
                break
            time.sleep(1.5 + random.random())  # back off, rotate, retry
        time.sleep(random.uniform(1, 3))         # pace between products
    return rows

検索、ベストセラーとページネーション

製品ページは詳細です;検索とベストセラーページは何を取得するかを発見する方法です。キーワード検索は/s?k=<query>&page=<n>です;ベストセラーはカテゴリブラウズノードに基づいています。ページを歩き、各結果カードからASINを引き出し、上記の製品ステージに供給します。2つのステージを分けておくことで、ASINを重複排除し、クロールを再開し、既知のASINリストをスケジュールで再価格設定することができます。より広範な構築のために、ウェブスクレイピングに最適なプロキシに関するガイドは、プール側をカバーしています。

出力自体については、行スキーマを平坦で安定させておきます:asin、ソースurltitlepricerating、レビュー数、image_url、取得した市場のdomainです。混合市場データセットが米国の価格と英国の価格を混同しないように、すべての行にドメインを書き込みます。価格が空でもASINをキャプチャします—在庫切れの読み取りはデータポイントであり、ギャップではなく、製品が在庫に出入りする時期を追跡することは、価格と同じくらい価値があります。これらの列を持つCSVまたはデータベーステーブルは、価格追跡、在庫アラート、またはBuy Box研究に問題なくフィードされます。

素朴なAmazonスクレイパーが壊れる原因(価格IDの欠落、CAPTCHA、IP禁止、間違った通貨)を修正するためのチェックリスト
ほぼすべてのAmazonスクレイピングの失敗はこれら5つのうちの1つであり、それぞれに具体的な修正があります。

プロキシとスクレイピングAPI:切り替える時

手作りのrequestsと良質な住宅プールは、ボリュームを制御し、ターゲットが協力的である間は正しい選択です。数千のASINを1日で維持し、回転セレクタ、CAPTCHA処理、地理固定、再試行ロジックを維持するようになると、そのメンテナンスが仕事になります。Scraper APIはそれを圧縮します:Amazon URLを送信し、回転、レンダリング、地理が処理された構造化製品データを受け取ります。正直なルール—摩擦が低いうちはDIY、アンチボットの維持がデータの価値よりも多くのエンジニアリング時間を要する時に切り替えます。構築対購入の内訳はそのラインに数値を置きます。

よくある質問

PythonでAmazon製品データをスクレイピングするにはどうすればいいですか?

/dp/<ASIN>で製品ページをrequestsと実際のブラウザUser-Agentで取得し、BeautifulSoupでタイトル、価格、評価、在庫状況を解析します。廃止されたpriceblock_ourpriceだけでなく、いくつかの価格セレクタを試してください。バーストがブロックを引き起こさないように回転する住宅プロキシを経由し、価格を取得したい市場に出口地理を固定します。

Amazon製品データをスクレイピングすることは合法ですか?

公に見える製品データ(タイトル、価格、評価)の収集は、一般的にログインを回避したり、保護されたコンテンツをコピーしたりすることとは異なりますが、Amazonの規約は自動化されたアクセスを制限しており、法的な状況は管轄区域や使用によって異なります。これは一般情報であり、法的アドバイスではありません:公のデータのみをスクレイピングし、レート制限を尊重し、商業的または境界線上のものには法律相談を受けてください。

なぜ私のAmazonスクレイパーはウェブサイトと異なる価格を取得するのですか?

Amazonは、IPから推測される配送先に価格と在庫状況をローカライズします。あなたのプロキシが調査している市場と異なる国で終了すると、間違った通貨やオファーが表示されます。ターゲット市場に出口IPを固定します—米国の価格には米国の住宅IP、英国の価格には英国のIPを使用します—そうすればデータはその市場の実際の購入者が見るものと一致します。

Amazonをスクレイピングする際にブロックを避けるにはどうすればいいですか?

多くの住宅IPを回転させ、1つのアドレスが負荷を担わないようにし、ランダムな遅延と同時実行制限でスロットルし、整合性のあるブラウザヘッダーを送信します。すべての応答を検証します—200でもロボットチェックページである可能性があります—そして、ブロックされたものを解析するのではなく、新しいIPで再試行します。大量の場合、Scraper APIがそれをすべて処理します。

Amazonを大規模に扱うのが難しいのは、解析が難しいからではなく、サイトが抵抗し、価格がどこに立っているかによって異なるからです。ASINを最初に構築し、いくつかの価格コンテナを一致させ、地理を固定し、IPを回転させ、短い応答をデータではなくブロックとして扱います。それらを正しく行えば、初心者向けチュートリアルがついにスケールします。

QuantumProxies Scraper APIでAmazonをスクレイピングする