如何在 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。

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 固定在你想要价格的市场。

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

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

获取地理定位的住宅代理

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

Amazon 运行自动请求管理系统:从一个 IP 爆发得太快,你会得到一个 CAPTCHA、IP 禁令或一个简化页面。三件事可以让抓取器在大批量时存活。首先,轮换 IP,这样没有单个地址承载整个负载——轮换住宅池将请求分散到许多真实消费者 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,然后将它们输入到上面的产品阶段。保持两个阶段分开——这样可以让你去重 ASIN,恢复抓取,并在不重新发现的情况下按计划重新定价已知的 ASIN 列表。对于更广泛的构建,我们的最佳网络抓取代理指南涵盖了这一点的池侧。

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

检查表映射出导致天真 Amazon 抓取器失败的原因(缺失的价格 ID、CAPTCHA、IP 禁令、错误的货币)及其解决方案
几乎每个 Amazon 抓取失败都是这五个之一——每个都有具体的解决方案。

代理与抓取 API:何时切换

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

常见问题解答

如何使用 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