我的 Amazon 评论爬虫连续稳定跑了六周——直到某天早上,它返回了 200 OK,但给我的却是一整页空白。没有报错,没有 CAPTCHA,只有原本该显示成百上千条评论的位置,变成了一片空荡荡的 HTML。
如果你也碰到过这种情况,那你一点都不孤单。到了 2025 年底,Amazon 已经开始把完整评论页挡在登录墙后面,导致大量 Python 爬虫脚本一夜之间失效。过去几个月里,我一边在 Thunderbit 做 AI 爬虫,一边维护自己的 Python 评论抓取流程,所以我觉得,现在正是把这份我当时最希望有人写给我的指南整理出来的时候。下面我会讲清楚一套真正能用的方法:基于 Cookie 的身份验证、能扛住 Amazon CSS 混淆的稳定选择器、绕过 10 页分页限制的办法、反爬防护策略,以及一个额外的情感分析章节,帮你把原始评论文本转成真正有价值的商业洞察。要是你看到一半心里冒出一句:“我其实不想维护这么多代码”,我也会演示 Thunderbit 如何用大概两分钟、零 Python 代码完成同样的事。
什么是 Amazon 评论抓取?为什么它很重要?
Amazon 评论抓取,指的是通过程序自动提取 Amazon 商品页上的用户评论数据——包括星级评分、评论内容、作者名称、日期、Verified Purchase(已验证购买)标记等。自从 Amazon 在 2010 年 从 Product Advertising API 中移除了评论内容 之后,而且再也没加回来,网页爬虫就成了获取这些数据的唯一程序化方式。
数据也在证明这件事。95% 的消费者会在购买前阅读评论,而且 94% 的人把 Amazon 视为他们获取产品评论的第一来源。在商品页上只展示 5 条评论,就能让转化率提升 270%。而那些系统化分析评论情绪的公司,客户留存率甚至可以 提高多达 15%。这不是抽象的数据科学,而是竞争情报、产品改进信号和营销话术,明明白白地躺在 Amazon 的服务器上。
为什么要用 Python 抓取 Amazon 评论
Python 依然是做这类工作的首选语言。它是 2024 年 Stack Overflow 开发者调查中最受欢迎的语言之一,而且它的生态——requests、BeautifulSoup、pandas、Scrapy——让网页爬虫即使对非全职开发者来说也很好上手。
不同团队会拿这些数据做不同的事:
| 团队 | 使用场景 | 提取内容 |
|---|---|---|
| 产品 / 研发 | 找出重复投诉,优先处理问题 | 1–2 星评论文本、关键词频率 |
| 销售 | 监控竞品产品口碑 | 评分、评论数量趋势 |
| 营销 | 提取客户语言用于广告文案 | 正向评论短语、功能提及 |
| 电商运营 | 跟踪自家产品口碑变化 | 星级分布、Verified Purchase 占比 |
| 市场研究 | 对比类目头部产品的功能表现 | 多 ASIN 评论数据集 |
某厨具品牌 分析负面评论后发现 22% 的用户提到“涂层脱落”,于是重新调整配方,60 天内就重新夺回了 #1 Best Seller 的位置。某智能手环公司 从评论文本中发现“表带刺激皮肤”,定位到乳胶过敏问题后,推出低敏版本,退货率下降了 40%。这种 ROI,足以说明投入工程成本是值得的。
登录墙:为什么你的 Amazon 评论爬虫突然失效了
2024 年 11 月 14 日,Amazon 开始要求用户登录才能查看完整的商品评论页。这项变化随后也在 社区论坛 和 爬虫服务商博客 中得到了确认。如果你在无痕窗口里访问 /product-reviews/{ASIN}/,看到的会是登录页面,而不是评论数据。

症状其实很隐蔽:你的脚本拿到了 200 OK,但 HTML 里塞进去的是登录表单(name="email"、id="ap_password"),而不是评论。没有错误码,没有 CAPTCHA。就是……啥也没有。
Amazon 这样做,一部分是为了反机器人,另一部分是为了满足地区合规要求。实际执行并不完全一致——有时候新的浏览器窗口在登录墙出现前还能看到几条评论,尤其是第一页——但对任何规模化爬虫来说,你都应该默认登录墙始终存在。
不同国家站点(.de、.co.uk、.co.jp)的登录墙是独立生效的。正如某个论坛用户说的:“每个国家都得单独登录。”你的 .com Cookie 不能直接用在 .co.uk 上。
Featured Reviews 与完整评论:不登录还能看到什么?
Amazon 商品页(/dp/{ASIN}/)在不认证的情况下,仍然会展示大约 8 条“精选评论”。这些评论是 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 位商品标识符。你会在任何商品 URL 里找到它——比如在 amazon.com/dp/B0BCNKKZ91 里,ASIN 就是 B0BCNKKZ91。这就是你后面要放进评论 URL 的关键值。
第 1 步:用基于 Cookie 的身份验证绕过登录墙
最稳妥的做法,是先在浏览器里登录 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 | 与用户邮箱相关的标识符 |
如何从 Chrome DevTools 提取 Cookie
- 在 Chrome 中登录 amazon.com
- 打开 DevTools(F12,或右键 → 检查)
- 进入 Application → Storage → Cookies →
https://www.amazon.com - 在表格里找到每个 Cookie 名称并复制它的值
- 组合成 Python 可用的分号分隔字符串
像下面这样设置你的 session:
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 通常能维持几天到几周;如果你又开始被重定向到登录页,就需要重新从浏览器里刷新一次。
对于非 .com 市场,Cookie 名称会略有不同——比如 amazon.de 用的是 at-acbde,amazon.co.uk 用的是 at-acbuk,等等。每个站点都需要单独的 session。
第 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")
有一个小技巧很好用:在访问评论页之前,先打开商品页。这样会让你的 session 看起来更像真实浏览行为。
# 先访问商品页(模拟正常浏览)
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 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 选择器的提取代码如下:
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 purchase
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 class 在同一时期至少轮换了两次。
第 4 步:处理分页与 Amazon 的 10 页上限
Amazon 会把 pageNumber 参数限制在最多 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} 页:{len(page_reviews)} 条评论")
如何抓取超过 10 页的 Amazon 评论
可行的绕过办法是分桶筛选。每一组 filterByStar + sortBy 组合,都会得到自己独立的 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} 页:{len(page_reviews)} 条评论")
print(f"唯一评论总数:{len(all_reviews)}")
不同桶之间会有重叠,所以去重非常必要。我通常用“评论标题 + 作者名”的组合做快速去重键——不完美,但能覆盖绝大多数重复项。
第 5 步:绕开反爬防线(轮换、限速、重试)
Amazon 使用 AWS WAF Bot Control,而且现在越来越激进了。单一层面的对抗手段(比如只换 User-Agent、只加延迟)已经不太够用了。
| 技巧 | 实现方式 |
|---|---|
| 轮换 User-Agent | 从 10+ 个真实浏览器字符串中随机选择 |
| 指数退避 | 遇到 503 时按 2 秒 → 4 秒 → 8 秒重试 |
| 请求限速 | 页面之间等待 random.uniform(2, 5) 秒 |
| 代理轮换 | 切换住宅代理 |
| 会话指纹 | 每个 session 保持一致的 Cookie + Header |
| TLS 伪装 | 生产环境用 curl_cffi 代替原生 requests |
一个适合生产环境的重试封装如下:
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 美元以上。对于小型项目(每天少于 100 次请求),从家用 IP 出发并配合合理限速,通常也能正常工作。
Amazon 还会检查 TLS 指纹。Python 原生的 requests 库有一个 众所周知、会被 WAF 预先拦截的 JA3 哈希。对于生产级爬虫,建议考虑 curl_cffi,它能伪装成真实浏览器的 TLS 栈。如果只是教程级别的抓取(几百页以内),requests 配合不错的 header 通常就够用了。
第 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")
示例输出:
| author | rating | title | content | date | country | verified |
|---|---|---|---|---|---|---|
| Sarah M. | 5.0 | 今年最值得买的东西 | Battery lasts all day, screen is gorgeous... | January 15, 2025 | the United States | True |
| Mike T. | 2.0 | 两周后很失望 | The charging port stopped working... | February 3, 2025 | the United States | True |
| Priya K. | 4.0 | 这个价格很值 | Does everything I need, minor lag on heavy apps... | March 10, 2025 | the United States | False |
导出 Excel 的话:df.to_excel("amazon_reviews.xlsx", index=False)(需要 openpyxl)。
如果你要导入 Google Sheets,可以用 gspread,但它需要 8 步以上的 Google Cloud 配置——创建项目、启用两个 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(截断) | rating | sentiment |
|---|---|---|
| "Battery lasts all day, screen is gorgeous..." | 5.0 | 0.65 |
| "The charging port stopped working after..." | 2.0 | -0.40 |
| "Does everything I need, minor lag on..." | 4.0 | 0.25 |
| "Absolute garbage. Returned immediately." | 1.0 | -0.75 |
| "It's okay. Nothing special but works." | 3.0 | 0.10 |
真正有意思的是那些“不一致”的行——比如 3 星评论却带着明显正向措辞,或者 5 星评论里却冒出负面表达。这些差异往往能揭示星级评分本身看不到的细腻用户观点。

如果你追求生产级准确率,推荐用 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 星评论单独拎出来,看里面反复出现的主题——那里通常藏着一个能修复的核心缺陷。
诚实的取舍:自己写 Python、付费爬虫 API,还是 Thunderbit
我维护过 Amazon 的 Python 爬虫,所以我得坦白:它们确实会坏。选择器会变,Cookie 会过期,Amazon 会上线新的反爬层,然后你原本该拿来分析数据的周六早上,就变成了调试爬虫。论坛里也能看到同样的抱怨——那些“上个月还好好的”脚本,现在都得不停打补丁。
下面是三种主流方案的对比:
| 对比项 | DIY Python(BS4/Selenium) | 付费爬虫 API | Thunderbit(无代码) |
|---|---|---|---|
| 上手时间 | 1–3 小时 | 30 分钟(API Key) | 2 分钟 |
| 成本 | 免费(+ 代理成本) | 每月 50–200 美元以上 | 提供免费额度 |
| 登录墙处理 | 手动管理 Cookie | 通常已处理 | 自动处理 |
| 维护成本 | 高(选择器会坏) | 低(服务商维护) | 几乎为零(AI 自适应) |
| 分页处理 | 需要自写代码 | 内置 | 内置 |
| 多国家站支持 | 每个域名单独 session | 通常支持 | 基于浏览器 = 跟随你的本地环境 |
| 情感分析 | 需自己写代码 | 有时包含 | 可导出到 Sheets,任意分析 |
| 最适合 | 学习、完全可控 | 生产级流水线 | 快速取数、非技术团队 |
Python 能给你完全控制权,而且确实是理解网页爬虫底层机制的最好方式。但如果你的需求是“周五前把竞品评论数据放进表格”,而不是“我要搭一个生产级数据管道”,那自己维护爬虫的成本可能就不划算了。
如何用 Thunderbit 抓取 Amazon 评论(无需代码、无需维护)
我们开发 Thunderbit 的初衷,就是专门应对那些“维护 Python 爬虫太折腾”的场景。流程很简单:
- 安装 Thunderbit Chrome 扩展
- 在浏览器中打开 Amazon 商品评论页(你已经登录了,所以登录墙不是问题)
- 点击“AI Suggest Fields”——Thunderbit 会自动读取页面并建议字段,比如作者、评分、标题、评论正文、日期、已验证购买
- 点击“Scrape”——数据会立刻被提取出来,并且内置分页处理
- 导出到 Excel、Google Sheets、Airtable 或 Notion
最大的优势在于,Thunderbit 的 AI 每次都会重新读取页面结构。你不用维护 CSS 选择器,也不用管 Cookie,更不用写反爬代码。只要 Amazon 的 HTML 结构变了,AI 就会自动适应。对于想要程序化访问但又不想从零手搓的人,Thunderbit 还提供 Extract API——通过 API 做结构化数据提取,AI 自动识别字段,无需维护选择器。
如果你想进一步了解 Amazon 数据,可以看看我们的指南:如何抓取 Amazon 商品和评论 以及 提取和分析 Amazon 销售数据。
用 Python 批量抓取 Amazon 评论的实用技巧
如果你要跨多个 ASIN 抓评论,下面这些做法能帮你少踩很多坑:
- 批量处理 ASIN,不仅页面之间要加延迟,商品与商品之间也要加。我通常在不同 ASIN 之间暂停 10–15 秒。
- 强力去重。 当你把不同星级筛选和排序组合拼在一起时,重复评论会很多。可以用
(title, author, date)元组作为去重键。 - 记录失败日志。 跟踪哪些 ASIN + 页面 + 筛选组合失败了,这样你就能只重试失败项,而不是全部重新抓一遍。
- 大项目请存数据库。 简单的 SQLite 比不断增长的 CSV 文件要稳得多:
import sqlite3
conn = sqlite3.connect("reviews.db")
df.to_sql("reviews", conn, if_exists="append", index=False)
- 定时抓取。 如果你要持续监控,可以设置 cron job,或者直接用 Thunderbit 的 Scheduled Scraper 功能——只要描述 URL 和计划,它会在不需要服务器的情况下自动把后续工作做完。
如果你想看更多方案,我们关于 最佳自动化网页爬虫工具 和 将网站数据抓取到 Excel 的文章也值得一看。
关于法律与伦理的简短说明
Amazon 的 使用条款 明确禁止“使用任何机器人、蜘蛛、爬虫或其他自动化方式访问 Amazon 服务”。不过,近年的美国判例对公开数据抓取相对友好。在 Meta Platforms v. Bright Data(2024 年 1 月) 一案中,联邦法院裁定:对公开可访问数据的抓取,如果爬虫并不是登录状态下的“用户”,并不违反服务条款。
但这里有个关键差别:如果你是在登录后抓取(也就是本文讲的做法),就会进入合同法范畴,因为你在注册账号时已经接受了 Amazon 的服务条款。相比之下,抓取公开可见的精选评论,法律风险会低一些。
实用建议:不要商业化再分发抓取来的数据,不要抓取超出公开展示范围的个人用户信息,尊重 robots.txt,大规模或商业用途请咨询法律顾问。这不是法律建议。想进一步了解法律环境,可以看看我们关于 网页爬虫法律影响 的概述。
结论:用 Python 抓 Amazon 评论,或者干脆跳过代码
快速回顾一下这篇指南讲了什么:
- 登录墙确实存在,但可以用基于 Cookie 的认证来解决——从浏览器里复制 7 个 Cookie,注入到
requests.Session()中即可 - 提取时用
data-hook选择器,不要依赖 CSS class,这样不会每隔几周就坏掉 - 通过组合星级筛选和排序方式,绕过 10 页分页上限,每个商品可访问 500+ 条评论
- 用 TextBlob 做快速基线,或用 Hugging Face Transformers 做生产级情感分析
- 维护反爬策略:限速、轮换 User-Agent、指数退避,以及在规模化时使用住宅代理
Python 能让你完全掌控流程,也是理解底层机制的最佳方式。但如果你的需求是“周五前把竞品评论数据放进电子表格”,而不是“我要搭一套生产级数据管道”,那么自己维护爬虫的成本可能就不划算了。
Thunderbit 可以通过点击完成身份验证、选择器、分页和导出——试试 免费版,看看它是否适合你的工作流。随着 Amazon 持续加码反爬措施,能够实时自适应的 AI 工具,未来只会越来越不是“锦上添花”,而是“必需品”。
你也可以访问我们的 Thunderbit YouTube 频道,观看更多抓取流程的视频演示。
常见问题
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 会更有用。想要一个能自动处理登录墙和分页的无代码替代方案,可以试试 Thunderbit。
5. 抓 Amazon 评论时如何避免被封?
从 10+ 个真实浏览器 User-Agent 字符串中轮换,设置每次请求之间 2–5 秒的随机延迟,在 503/429 错误时使用指数退避,规模化时使用住宅代理(数据中心 IP 往往会被预先拦截),并在整个请求过程中保持一致的 session Cookie。如果你想零维护,Thunderbit 会通过浏览器会话自动处理反爬防护。
了解更多


