我是如何用 Python 抓取 Amazon 评论的(绕过登录墙)

最后更新于 April 16, 2026

我的 Amazon 评论爬虫曾经连续稳定运行了整整六周——直到某天早上,它返回了 200 OK,但页面却空空如也。没有报错,没有 CAPTCHA,只有一片空白的 HTML,原本成百上千条评论的位置什么都没有了。

如果你也遇到过这种情况,那你并不孤单。到了 2025 年底,Amazon 开始把完整评论页挡在登录墙后面,导致大量 Python 爬虫脚本一夜之间失效。过去几个月里,我一直在 一边开发我们的 AI 爬虫,一边维护自己的 Python 评论采集流程,所以我觉得现在正是把当初我最希望拥有的这份指南写出来的时候。这篇文章会讲清楚一套真正可用的方法:基于 Cookie 的身份验证、能扛住 Amazon CSS 混淆的稳定选择器、突破 10 页分页限制的技巧、反爬应对策略,以及一个额外的情感分析部分,把原始评论文本变成真正有价值的商业洞察。如果你读到一半开始想:“我真的不想维护这么多代码”,我也会告诉你如何用 在大约两分钟内、几乎不写 Python 就完成同样的工作。

什么是 Amazon 评论抓取?为什么它重要?

Amazon 评论抓取,是指通过程序自动提取 Amazon 商品页面上的用户评论数据——包括星级评分、评论正文、作者名称、发布日期、是否为已验证购买等信息。由于 Amazon 早在 2010 年就从其 Product Advertising API 中移除了评论内容(而且再也没有恢复), 是获取这类数据的唯一程序化途径。

数据也证明了这一点。,而且 。在商品页只展示 5 条评论,就可能让 。系统分析评论情绪的公司,客户留存率可 。这不是什么抽象的数据科学概念,而是竞争情报、产品改进信号和营销文案素材,全都赤裸裸地躺在 Amazon 的服务器上。

为什么要用 Python 抓取 Amazon 评论

Python 依然是这类工作的首选语言。它是 中最受欢迎的语言之一,而 requests、BeautifulSoup、pandas、Scrapy 这些生态工具,也让即使不是全职开发者的人也能上手网页抓取。

不同团队会以不同方式使用这些数据:

团队使用场景提取内容
产品 / 研发识别高频抱怨,优先处理问题1–2 星评论文本、关键词频次
销售监控竞品口碑变化评分、评论量趋势
市场营销提取用户原话,用于广告文案正向评论短语、功能提及
电商运营跟踪自家产品口碑随时间变化星级分布、已验证购买比例
市场调研对比不同功能维度下的品类头部产品多 ASIN 评论数据集

某厨房用品品牌曾 ,于是重新调整配方,60 天内就重新夺回了 Best Seller 第一名。某健身追踪器公司则从 ,定位出乳胶过敏问题,推出低敏版本后,退货率下降了 40%。这类回报率,足以让工程投入变得非常值得。

登录墙:为什么你的 Amazon 评论爬虫突然失效了

2024 年 11 月 14 日起,。这一变化随后在 中得到了确认。如果你在无痕窗口访问 /product-reviews/{ASIN}/,看到的将是登录页,而不是评论数据。

python-web-scraping-diagram.webp

症状很隐蔽:脚本收到了 200 OK,但 HTML 正文里出现的是登录表单(如 name="email"id="ap_password"),而不是评论内容。没有错误码,没有 CAPTCHA,只有……什么都没有。

Amazon 这样做,主要是为了反机器人和地区合规。这个限制的执行并不完全一致——有时一个新的浏览器窗口在墙生效前还能看到几条评论,尤其是第一页——但对于任何规模化爬虫来说,都应该默认登录墙始终存在。

不同国家站点(.de.co.uk.co.jp)各自独立执行这道限制。正如论坛里有人说的:“每个国家都需要单独登录。”你的 .com Cookie 不会在 .co.uk 上生效。

精选评论 vs. 完整评论:不登录还能拿到什么

Amazon 商品页(/dp/{ASIN}/)在未认证状态下,仍然会展示大约 。这些评论是 Amazon 算法挑选出来的,适合快速做个口碑判断,但它们不能排序、不能筛选,也不能分页。

而完整评论页(/product-reviews/{ASIN}/)——可以按最新排序、按星级过滤,并跨数百条评论分页浏览——则需要登录。

如果你只需要少量评论做快速判断,抓商品页就够了;如果你要几百甚至上千条,就必须处理身份验证。

开始之前你需要什么:Python 环境与库

在写代码之前,先把环境准备好:

  • 难度: 中级(会 Python,懂一点 HTML 即可)
  • 所需时间: 完整流程约 45 分钟;基础抓取约 10 分钟
  • 你需要: Python 3.8+、Chrome 浏览器、一个有效的 Amazon 账号

安装核心库:

1pip install requests beautifulsoup4 lxml pandas textblob

可选安装(用于更高级的情感分析):

1pip install transformers torch

ASIN 是什么? 它是 Amazon 的 10 位商品标识。你可以在任何商品 URL 中找到它——例如在 amazon.com/dp/B0BCNKKZ91 里,ASIN 就是 B0BCNKKZ91。这就是你后面要放进评论 URL 的关键字段。

最稳妥的方法,是先在浏览器里登录 Amazon,复制会话 Cookie,再把它们注入到 Python 的 requests.Session() 中。这样可以避免 Selenium 自动登录经常触发的 CAPTCHA 和短信二次验证。

你需要这 7 个 Cookie:

Cookie 名称用途
session-id会话标识,可能会轮换
session-id-time会话时间戳
session-token会话令牌,可能会轮换
ubid-main用户浏览标识
at-main主要认证令牌
sess-at-main会话级认证信息
x-main与邮箱关联的用户标识
  1. 在 Chrome 中登录 amazon.com
  2. 打开 DevTools(F12,或右键 → 检查)
  3. 进入 ApplicationStorageCookieshttps://www.amazon.com
  4. 在上表中找到每个 Cookie 名称并复制其值
  5. 按分号分隔格式整理成 Python 可用字符串

这样设置你的 session:

1import requests
2session = requests.Session()
3# 把你的 Cookie 值贴在这里
4cookies = {
5    "session-id": "YOUR_SESSION_ID",
6    "session-id-time": "YOUR_SESSION_ID_TIME",
7    "session-token": "YOUR_SESSION_TOKEN",
8    "ubid-main": "YOUR_UBID_MAIN",
9    "at-main": "YOUR_AT_MAIN",
10    "sess-at-main": "YOUR_SESS_AT_MAIN",
11    "x-main": "YOUR_X_MAIN",
12}
13headers = {
14    "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",
15    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
16    "Accept-Language": "en-US,en;q=0.5",
17}
18session.cookies.update(cookies)
19session.headers.update(headers)

重要: 后续所有请求都复用同一个 session 对象。这样能保持 Cookie 一致,更像真实浏览器会话。Cookie 通常在高频抓取下可以维持几天到几周,但如果你又开始被重定向到登录页,就需要重新从浏览器刷新一次 Cookie。

对于非 .com 的站点,Cookie 名称会略有不同——amazon.de 使用的是 at-acbde 而不是 at-main,amazon.co.uk 用的是 at-acbuk,等等。每个站点都需要独立 session。

第二步:构造请求,并用 BeautifulSoup 解析评论 HTML

Amazon 评论页的 URL 模式如下:

1https://www.amazon.com/product-reviews/{ASIN}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber=1

核心函数如下:

1from bs4 import BeautifulSoup
2import time, random
3def get_soup(session, url):
4    time.sleep(random.uniform(2, 5))  # 礼貌性延迟
5    response = session.get(url, timeout=15)
6    # 检测登录墙
7    if "ap_email" in response.text or "Amazon Sign-In" in response.text:
8        raise Exception("检测到登录墙——请刷新你的 Cookie")
9    if response.status_code != 200:
10        raise Exception(f"HTTP {response.status_code}")
11    return BeautifulSoup(response.text, "lxml")

有个小技巧很有用:在进入评论页之前,先访问一次商品页。这会让你的 session 看起来更像正常浏览。

1# 先访问商品页(模拟真实浏览)
2product_url = f"https://www.amazon.com/dp/{asin}"
3session.get(product_url, timeout=15)
4time.sleep(random.uniform(1, 3))
5# 再访问评论页
6reviews_url = f"https://www.amazon.com/product-reviews/{asin}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber=1"
7soup = get_soup(session, reviews_url)

第三步:使用稳定选择器提取评论数据(别再依赖 CSS class 了)

这就是大多数 2022–2023 年教程失效的地方。Amazon 会混淆 CSS class 名称——它们会定期变化,正如某位苦恼的开发者在论坛里说的:“没有一个 span 标签的 class 名称是有规律的。”

解决办法是:Amazon 在评论元素上使用了 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 选择器的提取代码如下:

1import re
2def extract_reviews(soup):
3    reviews = []
4    review_divs = soup.select('[data-hook="review"]')
5    for div in review_divs:
6        # 星级评分
7        rating_el = div.select_one('[data-hook="review-star-rating"]')
8        rating = None
9        if rating_el:
10            rating_text = rating_el.get_text(strip=True)
11            match = re.search(r'(\d\.?\d?)', rating_text)
12            if match:
13                rating = float(match.group(1))
14        # 标题
15        title_el = div.select_one('[data-hook="review-title"]')
16        title = title_el.get_text(strip=True) if title_el else ""
17        # 正文
18        body_el = div.select_one('[data-hook="review-body"]')
19        body = body_el.get_text(strip=True) if body_el else ""
20        # 作者
21        author_el = div.select_one('span.a-profile-name')
22        author = author_el.get_text(strip=True) if author_el else ""
23        # 日期和国家/地区
24        date_el = div.select_one('[data-hook="review-date"]')
25        date_text = date_el.get_text(strip=True) if date_el else ""
26        # 格式示例:"Reviewed in the United States on January 15, 2025"
27        country_match = re.search(r'Reviewed in (.+?) on', date_text)
28        date_match = re.search(r'on (.+)$', date_text)
29        country = country_match.group(1) if country_match else ""
30        date = date_match.group(1) if date_match else ""
31        # 已验证购买
32        verified_el = div.select_one('[data-hook="avp-badge"]')
33        verified = bool(verified_el)
34        reviews.append({
35            "author": author,
36            "rating": rating,
37            "title": title,
38            "content": body,
39            "date": date,
40            "country": country,
41            "verified": verified,
42        })
43    return reviews

我已经用这套选择器在多个 ASIN 上连续跑了好几个月,data-hook 属性一次都没变过。反过来,CSS class 在同一时期至少轮换了两次。

第四步:处理分页,以及 Amazon 的 10 页上限

Amazon 会把 pageNumber 参数限制在每组筛选条件下最多 10 页,每页 10 条评论——也就是每个筛选组合硬性封顶大约 100 条评论。“下一页”按钮在第 10 页之后就会消失。

基础分页循环如下:

1all_reviews = []
2for page in range(1, 11):
3    url = f"https://www.amazon.com/product-reviews/{asin}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber={page}"
4    soup = get_soup(session, url)
5    page_reviews = extract_reviews(soup)
6    if not page_reviews:
7        break  # 这一页已经没有更多评论了
8    all_reviews.extend(page_reviews)
9    print(f"Page {page}: {len(page_reviews)} reviews")

如何抓取超过 10 页的 Amazon 评论

解决办法是“分桶筛选”。每一种 filterByStarsortBy 的组合,都会得到一个独立的 10 页窗口。

星级筛选值: one_startwo_starthree_starfour_starfive_star
排序值: recenthelpful(默认)

把 5 个星级筛选 × 2 个排序方式组合起来,你最多可以访问 100 页,也就是每个商品最多约 1,000 条评论;对于星级分布不均的商品,往往能接近完整评论集。

1star_filters = ["one_star", "two_star", "three_star", "four_star", "five_star"]
2sort_orders = ["recent", "helpful"]
3all_reviews = []
4seen_titles = set()  # 简单去重
5for star in star_filters:
6    for sort in sort_orders:
7        for page in range(1, 11):
8            url = (
9                f"https://www.amazon.com/product-reviews/{asin}"
10                f"?filterByStar={star}&sortBy={sort}&pageNumber={page}"
11            )
12            soup = get_soup(session, url)
13            page_reviews = extract_reviews(soup)
14            if not page_reviews:
15                break
16            for review in page_reviews:
17                # 用标题 + 作者组合去重
18                key = (review["title"], review["author"])
19                if key not in seen_titles:
20                    seen_titles.add(key)
21                    all_reviews.append(review)
22            print(f"[{star}/{sort}] Page {page}: {len(page_reviews)} reviews")
23print(f"Total unique reviews: {len(all_reviews)}")

不同分桶之间会有重叠,所以去重非常重要。我通常用“评论标题 + 作者名”的组合当作去重键——虽然不完美,但能过滤掉绝大多数重复项。

第五步:躲开反爬防线(轮换、限速、重试)

Amazon 使用的是 AWS WAF Bot Control,而且现在的检测强度明显更高了。单层对抗手段(只换 User-Agent,或只加延迟)已经不够用了。

技巧实现方式
轮换 User-Agent从 10+ 种真实浏览器字符串中随机选择
指数退避遇到 503 时按 2s → 4s → 8s 递增重试
请求限速每页之间等待 random.uniform(2, 5)
代理轮换循环使用住宅代理
会话指纹一致性同一 session 保持相同 Cookie + Headers
TLS 伪装生产环境中用 curl_cffi 代替原生 requests

一个适合生产环境的重试包装器:

1import time, random
2USER_AGENTS = [
3    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
4    "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",
5    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0",
6    "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",
7    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
8]
9def scrape_with_retries(session, url, max_retries=3):
10    for attempt in range(max_retries):
11        try:
12            session.headers["User-Agent"] = random.choice(USER_AGENTS)
13            time.sleep(random.uniform(2, 5))
14            response = session.get(url, timeout=15)
15            # 检测封锁
16            if "validateCaptcha" in response.url or "Robot Check" in response.text:
17                wait = (2 ** attempt) * 5
18                print(f"检测到 CAPTCHA。等待 {wait}s...")
19                time.sleep(wait)
20                continue
21            if response.status_code in (429, 503):
22                wait = (2 ** attempt) * 2
23                print(f"请求被限流({response.status_code})。等待 {wait}s...")
24                time.sleep(wait)
25                continue
26            if "ap_email" in response.text:
27                raise Exception("登录墙——Cookie 已过期")
28            return BeautifulSoup(response.text, "lxml")
29        except Exception as e:
30            if attempt == max_retries - 1:
31                raise
32            print(f"第 {attempt + 1} 次尝试失败:{e}")
33    return None

关于代理:Amazon 会在网络层封禁已知的数据中心 IP 段(AWS、GCP、Azure、DigitalOcean)。如果你抓取的页面超过几百页,住宅代理几乎是必须的——根据规模不同,成本大约是每月 50–200 美元甚至更高。对于小项目(每天少于 100 次请求),从家用 IP 谨慎限速通常也够用。

Amazon 还会检查 TLS 指纹。Python 原生 requests 库有一个 。如果是生产级爬虫,可以考虑 curl_cffi,它可以伪装成真实浏览器的 TLS 栈。对于教程级别的抓取(几百页以内),带好请求头的 requests 往往就能完成任务。

第六步:把抓到的 Amazon 评论导出为 CSV 或 Excel

评论抓完之后,用 pandas 处理成可用格式非常简单:

1import pandas as pd
2df = pd.DataFrame(all_reviews)
3df.to_csv("amazon_reviews.csv", index=False)
4print(f"Exported {len(df)} reviews to amazon_reviews.csv")

示例输出:

authorratingtitlecontentdatecountryverified
Sarah M.5.0Best purchase this yearBattery lasts all day, screen is gorgeous...January 15, 2025the United StatesTrue
Mike T.2.0Disappointed after 2 weeksThe charging port stopped working...February 3, 2025the United StatesTrue
Priya K.4.0Great value for the priceDoes everything I need, minor lag on heavy apps...March 10, 2025the United StatesFalse

导出到 Excel:df.to_excel("amazon_reviews.xlsx", index=False)(需要 openpyxl)。

如果要导出到 Google Sheets,gspread 库可以用,但配置步骤有 ——创建项目、启用两个 API、生成服务账号凭据、共享表格。要是你觉得这比真正抓取还麻烦,那你没感觉错。(这也是为什么像 这样能一键导出到 Google Sheets 的工具,会突然变得特别有吸引力。)

额外收获:用 5 行 Python 给评论加上情感分析

大多数抓取教程都会在 CSV 导出这里停下。但真正把原始数据变成业务决策的,是情感评分。

最快的基线方案是 TextBlob:

1from textblob import TextBlob
2df["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。,而且与词典类工具相比,nlptown/bert-base-multilingual-uncased-sentiment 这个模型甚至可以直接预测 1–5 星:

1from transformers import pipeline
2clf = pipeline("sentiment-analysis",
3               model="nlptown/bert-base-multilingual-uncased-sentiment")
4df["predicted_stars"] = df["content"].apply(
5    lambda x: int(clf(str(x)[:512])[0]["label"][0])
6)

Amazon 评论通常呈现 ——5 星处有一个大峰值,1 星处有一个较小峰值,中间则形成低谷。这意味着平均星级往往并不能真实代表产品质量。最好把 1 星评论单独拿出来,提取其中反复出现的主题——通常真正可修复的问题,就藏在这里。

诚实的取舍:自建 Python、付费 API,还是 Thunderbit

我自己维护过 Amazon 的 Python 爬虫,所以我可以坦白地说:它们真的会坏。选择器会变,Cookie 会过期,Amazon 会上线新的反爬层,然后你的周六上午就变成了修爬虫,而不是分析数据。论坛里的用户也有同样的感受——那些“上个月还能跑”的 DIY 脚本,现在需要不停打补丁。

下面是三种主流方案的对比:

对比项自建 Python(BS4/Selenium)付费爬取 APIThunderbit(无代码)
上手时间1–3 小时30 分钟(API Key)2 分钟
成本免费(+ 代理成本)每月 50–200 美元以上有免费额度
登录墙处理手动管理 Cookie通常已处理自动处理
维护成本高(选择器容易失效)低(由服务商维护)几乎为零(AI 自适应)
分页支持需要自写代码内置内置
多国家支持每个域名独立 session通常支持基于浏览器 = 使用你的本地环境
情感分析需要自己写代码有时包含导出到表格后可在任意地方分析
最适合学习、完全控制规模化生产管道快速取数、非开发团队

Python 让你拥有完整控制权,而且确实是理解网页抓取底层机制的最佳方式。但如果你的需求是“周五前把竞品评论数据放进表格里”,而不是“我要搭一个生产级数据管道”,那么自定义爬虫的维护成本可能并不划算。

可以通过点击完成身份验证、选择器、分页和导出——试试 ,看看它是否适合你的工作流。随着 Amazon 不断加强反爬措施,能够实时自适应的 AI 工具,未来会从“加分项”变成“必需品”。

你也可以查看我们的 ,那里有抓取流程的视频演示。

常见问题

1. 不登录可以抓取 Amazon 评论吗?

可以,但只能拿到商品详情页(/dp/{ASIN}/)上显示的约 8 条“精选评论”。截至 2024 年底,带排序、筛选和分页的完整评论页都需要认证。对大多数业务场景来说,你还是要处理登录墙。

2. 抓取 Amazon 评论合法吗?

Amazon 的服务条款禁止自动化抓取。不过,近期美国判例(Meta v. Bright Data,2024;hiQ v. LinkedIn)支持抓取公开可访问数据。由于你已经同意了 Amazon 的条款,登录后抓取的法律风险会更高。商业使用请咨询律师。

3. 每个商品最多能抓多少条 Amazon 评论?

Amazon 对每个排序和星级筛选组合限制最多 10 页。利用 5 个星级筛选 × 2 个排序方式,单个商品最多可访问 100 页(大约 1,000 条评论)。如果再加关键词筛选,理论上上限更高,但重复数据也会更多。

4. 抓取 Amazon 评论最好的 Python 库是什么?

requests + BeautifulSoup 是最常见也最稳定的静态 HTML 解析组合。如果需要 JavaScript 渲染,Selenium 会更有用。想要一个不写代码、还能自动处理登录墙和分页的替代方案,可以试试

5. 抓取 Amazon 时,怎么避免被封?

从 10+ 种真实浏览器的 User-Agent 中轮换,给每次请求加入 2–5 秒的随机延迟,对 503/429 错误做指数退避,规模化时使用住宅代理(数据中心 IP 往往会被预先封禁),并保持请求之间的 Cookie 一致性。如果你想完全省心,Thunderbit 会通过你的浏览器会话自动处理反爬防御。

了解更多

Fawad Khan
Fawad Khan
Fawad writes for a living, and honestly, he kind of loves it. He's spent years figuring out what makes a line of copy stick — and what makes readers scroll past. Ask him about marketing, and he'll talk for hours. Ask him about carbonara, and he'll talk longer.
目录

试试 Thunderbit

只需 2 次点击即可抓取线索和其他数据。AI 驱动。

获取 Thunderbit 免费使用
使用 AI 提取数据
轻松将数据传输到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week