# 如何在 Python 中大规模抓取 Amazon 产品数据

三行 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?`下，带有查询和浏览节点参数。因此，可扩展的抓取流程有两个阶段：从搜索或畅销商品页面发现 ASIN，然后从其`/dp/`页面获取详细信息。有一个注意事项——“父”ASIN（有尺寸或颜色变体的产品）会自动选择一个子变体，所以要捕捉到你实际访问的变体 ASIN。

```python
import requests
from bs4 import BeautifulSoup

PROXY = "http://USER:PASS@residentialpremium.quantumproxies.io:8080"
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 在大多数页面上是空的。持久的方法是按顺序尝试几个已知的价格容器，并选择第一个匹配的——并将缺失的价格视为一种真实状态（通常是缺货），而不是崩溃。

```python
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 列表、固定在目标市场的出口 IP、对每个 /dp/ 页面进行 hydration 以获取标题、价格和评分，然后输出为扁平 CSV 行；卡片展示了行结构，每一行都写入了 Amazon 站点域名。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335159/blog/generated/qp-b9-021-diag1.png)
*从搜索中发现 ASIN，从其 /dp/ 页面获取详细信息，并将出口 IP 固定在你想要价格的市场。*

## 为什么同一产品显示两个价格

这就是悄悄破坏定价数据集的事实。Amazon 根据购物者的交付位置——“送到”设置——本地化价格和可用性，主要从你的 IP 推断。用德国数据中心 IP 抓取`amazon.com`，你可能会得到欧元定价、不同的报价，或与美国购物者看到的不同的购买框赢家。如果你在收集[竞争性定价数据](https://quantumproxies.io/blog/competitor-price-monitoring-with-proxies)，出口 IP 的地理位置*就是*实验：要捕捉美国买家看到的价格，你需要通过美国[住宅代理](https://quantumproxies.io/residential-proxies)；对于英国市场，则需要英国出口。一个产品，多个价格，每个市场一个样本。

[获取地理定位的住宅代理](https://quantumproxies.io/residential-proxies)

## 为什么天真的抓取器会被封锁

Amazon 运行自动请求管理系统：从一个 IP 爆发得太快，你会得到一个 CAPTCHA、IP 禁令或一个简化页面。三件事可以让抓取器在大批量时存活。首先，轮换 IP，这样没有单个地址承载整个负载——轮换住宅池将请求分散到许多真实消费者 IP。其次，控制节奏：随机延迟和并发限制，而不是全速循环。第三，发送一致的头信息——真实浏览器的 User-Agent 和`Accept-Language`，而不是默认的 Python 字符串。当页面返回异常短或包含机器人检查标记时，丢弃它并在新 IP 上重试，而不是解析垃圾数据。

```python
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，然后将它们输入到上面的产品阶段。保持两个阶段分开——这样可以让你去重 ASIN，恢复抓取，并在不重新发现的情况下按计划重新定价已知的 ASIN 列表。对于更广泛的构建，我们的[最佳网络抓取代理指南](https://quantumproxies.io/blog/best-proxies-for-web-scraping)涵盖了这一点的池侧。

对于输出本身，保持行模式扁平且稳定：一个`asin`，来源`url`，`title`，`price`，`rating`，评论数，一个`image_url`和抓取的市场`domain`。在每行中写入域，以便混合市场数据集不会将美国价格与英国价格混淆。即使价格为空，也要捕获 ASIN——缺货读数是一个数据点，而不是一个空白，并且跟踪产品何时进出库存通常与价格一样有价值。具有这些列的 CSV 或数据库表可以无缝地输入到价格跟踪、可用性警报或购买框研究中，而无需进一步重塑。

![标出简单粗暴的抓取器在哪里失效的 Amazon 商品页面：旧的 priceblock_ourprice ID 为空，价格和货币随 IP 所在地而变化，200 也可能是机器人验证页面，单个 IP 的突发请求会被封；卡片给出了每个问题的解决方法，从使用多个价格选择器到带随机延迟的轮换。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335159/blog/generated/qp-b9-021-diag2.png)
*几乎每个 Amazon 抓取失败都是这五个之一——每个都有具体的解决方案。*

## 代理与抓取 API：何时切换

手工编写的`requests`加上一个好的住宅池是你控制流量和目标保持合作时的正确选择。一旦你每天要维护数千个 ASIN 的轮换选择器、CAPTCHA 处理、地理定位和重试逻辑，这项维护就成了工作。一个[Scraper API](https://quantumproxies.io/scraper-api)可以简化这一切：发送一个 Amazon URL，返回结构化的产品数据，轮换、渲染和地理处理都为你完成。诚实的规则是——当摩擦较小时自制，当反机器人维护花费的工程时间超过数据价值时切换。我们的[构建与购买](https://quantumproxies.io/blog/build-vs-buy-scraping-infrastructure)分析为这一界限提供了数据。

## 常见问题解答

### 如何使用 Python 抓取 Amazon 产品数据？

使用`requests`和真实浏览器 User-Agent 获取`/dp/<ASIN>`的产品页面，然后用 BeautifulSoup 解析标题、价格、评分和可用性。尝试多个价格选择器，而不仅仅是已弃用的`priceblock_ourprice`。通过轮换住宅代理路由，以防止突发触发封锁，并将出口地理位置固定在你想要定价的市场。

### 抓取 Amazon 产品数据是否合法？

收集公开可见的产品数据——标题、价格、评分——通常与绕过登录或复制受保护内容不同，但 Amazon 的条款限制自动访问，法律情况因司法管辖区和用途而异。这是一般信息，不是法律建议：仅抓取公共数据，遵守速率限制，并为任何商业或边界情况寻求法律建议。

### 为什么我的 Amazon 抓取器得到的价格与网站不同？

Amazon 根据从你的 IP 推断的交付位置本地化定价和可用性。如果你的代理出口在与你研究的市场不同的国家，你会看到错误的货币和报价。将出口 IP 固定在目标市场——美国价格用美国住宅 IP，英国价格用英国 IP——以便数据与那里的真实购物者看到的相匹配。

### 如何避免在抓取 Amazon 时被封锁？

在多个住宅 IP 上轮换，这样没有单个地址承载负载，使用随机延迟和并发限制进行节流，并发送一致的浏览器头信息。验证每个响应——200 仍然可能是一个机器人检查页面——并在新 IP 上重试，而不是解析被封锁的页面。在高流量时，Scraper API 为你处理所有这些。

大规模抓取 Amazon 并不难，因为解析困难——难在于网站反击，价格取决于你所处的位置。以 ASIN 为首，匹配多个价格容器，固定你的地理位置，轮换你的 IP，并将短响应视为封锁，而不是数据。做好这些，初学者教程终于可以扩展。

[使用 QuantumProxies Scraper API 抓取 Amazon](https://quantumproxies.io/scraper-api)
