Amazon反爬虫:一场从自动化到Chrome插件的折腾之旅
做个市场分析而已,Amazon至于。
起因:我就想抓点数据
2026年4月,想做一个电动助力自行车(ebike)的市场分析。目标很简单:去Amazon上抓个百八十个产品,分析一下价格、评分、品牌分布。
听起来很简单对吧?我当时也是这么想的。
先交代一下我的环境:Win10,8G内存的Core i3老笔记本,普通家庭宽带。后来证明,这个环境配置本身已经注定了故事的结局。
第一回合:Scrapling + Playwright,信心满满
一开始装了 Scrapling 和 Playwright,这两个工具看着挺靠谱的。先写个简单的测试脚本:
python
# Python --- 初次尝试 Scrapling
from scrapling import Fetcher
f = Fetcher()
page = f.get('https://www.amazon.com/s?k=electric+bike')
# 选择器提取产品卡片
cards = page.css('[data-asin]:not([data-asin=""])')
print(f"找到 {len(cards)} 个产品")
for card in cards[:5]:
title = card.css('h2 a').attrib['aria-label']
price_whole = card.css('.a-price-whole')
price = price_whole[0].text if price_whole else 'N/A'
print(f"{title[:50]}... | ${price}")
头一轮测试结果相当不错:
2026-04-08 11:26 --- 关键词 "electric bike"
搜索页成功识别 12 个产品
无头浏览器技术验证成功 ✅
接下来优化选择器。Amazon的页面结构经常变,同一个位置可能有不同的class名,所以必须弄一套主备选择器策略。
python
# Python --- 多选择器兜底策略
def extract_product_info(soup):
result = {}
# 标题:主备 4 个选择器
title_selectors = [
'#productTitle',
'h1.a-size-large',
'h1.a-size-extra-large',
'.product-title-word-break'
]
result['title'] = first_match(soup, title_selectors)
# 价格:主备 6 个选择器
price_selectors = [
'.a-price .a-offscreen',
'.a-price-whole',
'#priceblock_ourprice',
'#priceblock_dealprice',
'.a-color-price',
'.priceToPay'
]
result['price'] = first_match(soup, price_selectors)
# 评分:主备 8 个选择器
rating_selectors = [
'.a-icon-alt',
'i.a-icon-star span',
'[data-hook="rating-out-of-text"]',
'.a-star-4-5',
'.a-star-4',
'.a-star-5',
'.a-star-3',
'#acrPopover'
]
result['rating'] = first_match(soup, rating_selectors)
return result
选择器优化后,提取率全面提升:
| 字段 | 优化前 | 优化后 |
|---|---|---|
| 产品名称 | --- | 100% ✅ |
| 价格 | 75% | 100% ✅ |
| 评分 | 0% | 93.8% ✅ |
| 评价数量 | --- | 93.8% ✅ |
小批量测试全部通过:
关键词 "electric bike":3个产品,全部字段100% ✅
关键词 "electric bicycle":3个产品,全部字段100% ✅
总计:6个产品,100%提取率
生产系统验证通过 🎉
这时候我感觉这事儿稳了。
第二回合:选择器越写越多,问题越挖越深
产品详情页比搜索结果页复杂得多,不同字段需要不同的提取策略。
javascript
// JavaScript --- 商品详情页提取(content.js核心代码)
// 这是一对多的选择器兜底方案
function extractTitle() {
const selectors = [
'#productTitle', // 标准商品页
'#title', // 部分变种页
'h1.a-size-large', // 备用
'h1.a-size-extra-large', // 备用
'.product-title-word-break' // 备用
];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el && el.textContent.trim()) {
return el.textContent.trim();
}
}
return '';
}
function extractPrice() {
const selectors = [
'.a-price .a-offscreen', // 新版价格标签
'.a-price-whole', // 整数部分
'#priceblock_ourprice', // 标准价格
'#priceblock_dealprice', // 促销价格
'.a-color-price', // 颜色变体价格
'.priceToPay' // 最终支付价
];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el) {
const text = el.textContent.trim();
const match = text.match(/[\d.,]+/);
if (match) return { text, numeric: parseFloat(match[0]) };
}
}
return { text: '', numeric: 0 };
}
有些字段光靠CSS选择器还不够,还得上正则:
javascript
// JavaScript --- 评分和评论数提取
function extractRating() {
const selectors = [
'#acrPopover',
'.a-icon-star',
'[data-hook="rating-out-of-text"]'
];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el) {
const text = el.textContent || el.getAttribute('aria-label') || '';
// 匹配 "4.5 out of 5" 这种格式
const match = text.match(/(\d+\.?\d*)\s*out of 5/);
if (match) return parseFloat(match[1]);
}
}
return 0;
}
function extractReviewCount() {
const selectors = [
'#acrCustomerReviewText',
'#histogramTable .a-link-normal',
'[data-hook="total-review-count"]'
];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el) {
// 匹配 "1,234" 这种数字格式
const match = el.textContent.trim().match(/([\d,]+)/);
if (match) return parseInt(match[1].replace(/,/g, ''), 10);
}
}
return 0;
}
甚至遇到了4个产品没价格,查了半天发现不是技术问题------是Amazon的UI设计,有些产品(特别是多变体的)需要点击"See options"才能展开价格。这个自动化脚本没法处理,除非你模拟点击。但模拟点击又会触发行为检测......
后来还折腾了详情页的提取,像商品描述、品牌、图片、规格参数:
javascript
// JavaScript --- 商品详情提取
function extractDescription() {
const selectors = [
'#productDescription', // 标准描述
'#feature-bullets', // 卖点列表
'.aplus-v2', // A+ 页面内容
'.product-description' // 备用
];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el) return el.textContent.trim().replace(/\s+/g, ' ');
}
return '';
}
选择器文件一路从5个兜底涨到16个(评分)和12个(评价数)。提取率也从不到10%拉升到了100%。
但这都不重要了------因为接下来发生的事,让所有这些优化都变成了白费。
第三回合:100%验证码,当头一棒
就在我准备开始大规模抓取的时候,验证码来了。
一开始以为是偶发的。再试一次------验证码。换个关键词------验证码。换个浏览器引擎------还是验证码。
我开始系统地排查:
第一轮:换关键词
"electric bike" → ❌ 验证码 (5.1秒响应)
"electric bicycle" → ❌ 验证码 (4.8秒响应)
"ebike" → ❌ 验证码 (3.2秒响应)
"mountain bike" → ❌ 验证码 (5.5秒响应)
第二轮:怀疑是品类问题
"black tea" → ❌ 验证码 (5.1秒响应)
"红茶" → ❌ 验证码 (2.4秒响应)
第三轮:换工具
Playwright Chromium → ❌ 验证码
Playwright Firefox → ❌ 验证码
Playwright WebKit → ❌ 验证码
Scrapling → ❌ 验证码
直接 HTTP 请求 → ❌ 被屏蔽
测试结果汇总:
- 总测试关键词:6+个
- 成功访问:0个(0%成功率)
- 验证码检测:6次(100%出现率)
- 超时错误:0次
- 连接错误:0次
- 不同工具测试:全部失败
那一刻我就明白了------不是技术问题。是我这个IP已经被Amazon完全标记了。不只是我,是这台电脑、这个网络、这个环境,全被标记了。
我甚至在 PowerShell 里写了个脚本,直接往本地运行的浏览器里注入JavaScript来操作:
powershell
# PowerShell --- 通过本地浏览器接口操作
$body = @{
action = "evaluate"
args = @{
code = @"
document.querySelector('#twotabsearchtextbox').value = 'personalized glass mug';
document.querySelector('input[type=submit]').click();
"@
}
session = "amazon-test"
} | ConvertTo-Json -Compress
curl.exe -s -X POST http://127.0.0.1:10086/command `
-H "Content-Type: application/json" -d $body
结果?连"glass mug"这种完全无关的关键词都触发验证码。无差别封锁,确认。
第四回合:第一个Chrome插件------商品详情提取器
既然自动化行不通,那就换个思路:让真人操作浏览器,我写个插件辅助提取数据。
说干就干。开发时间是2026-04-10,从11:53到12:29,大约36分钟。
插件架构
Amazon_Product_Extractor/
├── manifest.json # 插件配置文件 (Manifest V3)
├── background.js # 后台 Service Worker
├── content.js # 内容提取脚本 (主力)
├── auto_extract.js # 自动提取模块
├── popup/
│ └── popup.html # 弹出界面
├── icons/
│ ├── icon16.png
│ ├── icon48.png
│ └── icon128.png
└── libs/
└── ...
manifest.json
json
{
"manifest_version": 3,
"name": "Amazon商品详情提取器",
"version": "1.1.0",
"description": "提取亚马逊商品详情页面信息并保存为JSON文件",
"permissions": [
"activeTab",
"downloads",
"scripting",
"storage",
"notifications",
"tabs"
],
"host_permissions": [
"https://www.amazon.com/*",
"https://www.amazon.co.jp/*",
"https://www.amazon.co.uk/*",
"https://www.amazon.de/*",
"https://www.amazon.fr/*",
"https://www.amazon.com.au/*"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup/popup.html"
},
"content_scripts": [
{
"matches": [
"https://www.amazon.com/*/dp/*",
"https://www.amazon.com/dp/*",
"https://www.amazon.co.jp/*/dp/*",
"https://www.amazon.co.uk/*/dp/*"
],
"js": ["content.js"],
"run_at": "document_idle"
}
]
}
注意这里的 content_scripts 的 matches,我只写了 /*/dp/* 和 /dp/* 两种URL模式,覆盖 .com、.co.jp、.co.uk 几个站点。后来你会发现这个模式在其他插件里扩展到了9个、12个甚至18个站点。
后台 Service Worker(background.js)
javascript
// JavaScript --- 后台脚本 (Service Worker)
console.log('[Background] 后台脚本启动 v1.1.0');
// Service Worker 需要保活机制
let keepAliveTimer = null;
function keepAlive() {
if (keepAliveTimer) clearTimeout(keepAliveTimer);
keepAliveTimer = setTimeout(() => {
console.log('[Background] 保持活动');
keepAlive();
}, 25000);
}
keepAlive();
// 接收弹出窗口请求,转发到内容脚本
async function extractProductInfo(tabId) {
try {
const response = await chrome.tabs.sendMessage(tabId, {
action: 'extract_product_info'
});
if (!response || !response.success) {
throw new Error('提取失败: ' + (response?.error || '未知错误'));
}
return response.data;
} catch (err) {
console.error('[Background] 提取错误:', err);
throw err;
}
}
内容脚本核心(content.js)
从URL中提取ASIN是第一步:
javascript
// JavaScript --- ASIN 提取
function extractASINFromURL() {
const url = window.location.href;
// 匹配 /dp/ASIN 格式
const dpMatch = url.match(/\/dp\/([A-Z0-9]{10})/);
if (dpMatch) return dpMatch[1];
// 匹配 /gp/product/ASIN 格式
const gpMatch = url.match(/\/gp\/product\/([A-Z0-9]{10})/);
if (gpMatch) return gpMatch[1];
return null;
}
自动提取模块(auto_extract.js)
考虑到页面可能还没加载完,加了个重试机制:
javascript
// JavaScript --- 自动提取模块(带重试)
function startExtract() {
console.log('[AutoExtract] startExtract 被调用');
if (typeof window.extractProductInfo !== 'function') {
console.log('[AutoExtract] 提取函数不可用,1秒后重试');
setTimeout(function() {
if (typeof window.extractProductInfo === 'function') {
doExtract();
} else {
console.log('[AutoExtract] 重试失败,放弃');
}
}, 1000);
return;
}
doExtract();
}
提取流程
用户打开Amazon商品详情页 → 点击插件图标 → 弹出窗口点击"提取" → 内容脚本读取页面数据 → 数据传给后台 → 保存为JSON/CSV文件。
整个过程不需要任何API调用,也不需要绕过任何反爬虫------因为浏览器是真人操作的,Amazon完全识别为正常用户。
第五回合:安装翻车
插件写好后,进行安装测试。Chrome 加载扩展后,点开详情页,点击插件------报错了:
TypeError: Cannot read properties of undefined (reading 'create')
打开控制台一看,是 background.js 里调用了 chrome.notifications.create() 想弹个通知告诉用户"提取成功",但 manifest.json 里忘了加 "notifications" 权限。
javascript
// ❌ 出错代码
chrome.notifications.create({
type: 'basic',
iconUrl: 'icons/icon48.png',
title: '提取完成',
message: '商品信息已保存'
});
// ✅ 修复:manifest.json 的 permissions 加上 "notifications"
try {
chrome.notifications.create({ ... });
} catch (e) {
console.warn('通知发送失败(可能无权限):', e);
}
修好之后,插件就能正常工作了。但这时候我发现了一个问题------提取一个商品就要手动点一次插件。如果我要提取100个商品,就得点100次。于是我开始琢磨:能不能批量搞?
第六回合:插件矩阵成形------从单兵作战到兵团协同
一个插件不够用,那多做几个呗。每个专注一个功能,组合起来形成完整的流水线。
到了2026年4月底,我已经搞出了4个插件,分工明确:
┌──────────────────┐
│ amazon_search_opener │
│ (搜索页→检测ASIN→打开) │
└────────┬─────────┘
│ 自动在新标签页打开
▼
┌──────────────────┐ ┌──────────────────┐
│ search_extractor │ │ product_extractor │
│ (搜索页提取信息) │ │ (详情页提取完整数据)│
└──────────────────┘ └────────┬─────────┘
│ 需要批量处理时
▼
┌──────────────────┐
│ ASIN_Opener │
│ (文件→批量打开页面)│
└──────────────────┘
插件1:Amazon 搜索结果提取器 v1.2.0
功能:打开Amazon搜索页面后,一键提取当前页面上所有产品信息。
json
// JSON --- manifest.json(搜索结果提取器)
{
"manifest_version": 3,
"name": "Amazon搜索结果提取器",
"version": "1.2.0",
"description": "提取Amazon关键字搜索结果页面的商品信息",
"permissions": [
"activeTab", "downloads", "scripting", "storage"
],
"host_permissions": [
"https://www.amazon.com/*",
"https://www.amazon.co.jp/*",
"https://www.amazon.co.uk/*",
"https://www.amazon.de/*",
"https://www.amazon.fr/*",
"https://www.amazon.com.au/*",
// ... 一共18个站点!
"https://www.amazon.in/*",
"https://www.amazon.sg/*",
"https://www.amazon.ae/*",
"https://www.amazon.sa/*",
"https://www.amazon.tr/*",
"https://www.amazon.com.br/*"
]
}
注意这个插件的 host_permissions 覆盖了 18个Amazon国家站点------从北美、欧洲、亚太到中东、南美,几乎全覆盖。因为我在项目中发现,分析不同站点的数据有时能发现很多有趣的差异。
提取逻辑和之前的商品详情提取器类似,但针对的是搜索页的列表结构:
javascript
// JavaScript --- 搜索结果提取器(搜索页提取 v1.2.0)
const CONFIG = {
selectors: {
productContainers: [
'div[data-component-type="s-search-result"][data-asin]',
'div[data-component-type="s-search-result"]',
'.s-result-item[data-asin]'
],
title: [
'h2 a span',
'.a-size-medium.a-color-base.a-text-normal',
'.a-size-base-plus.a-color-base.a-text-normal',
'h2.a-size-mini a span'
],
price: [
'.a-price .a-offscreen',
'.a-price-whole',
'.a-price span[aria-hidden="true"]',
'.a-color-price'
],
rating: [
'.a-icon-star-small .a-icon-alt',
'.a-icon-alt',
'i.a-icon-star-small'
],
reviewCount: [
'.a-size-base.s-underline-text',
'.a-size-base',
'.a-link-normal .a-size-base'
],
image: [
'.s-image',
'img.s-image',
'[data-image-latency="s-product-image"]'
]
// ... 每个字段都有3-5个兜底选择器
}
};
这个插件的思路是:你在Amazon搜了个关键词,出来一页结果,点一下插件,当前页所有商品的信息就提取下来了。不用一个个点开商品详情页。
对比单页提取和搜索页提取:
| 方式 | 单页操作 | 批量操作 |
|---|---|---|
| 商品详情提取器 | 点1次 → 拿1个 | --- |
| 搜索结果提取器 | --- | 点1次 → 拿一页(16~48个) |
插件2:Amazon Search Opener v1.4.7
这个插件的功能很纯粹:在搜索结果页面检测出所有不重复的ASIN,然后一键在新标签页打开所有商品详情。
javascript
// JavaScript --- Search Opener v1.4.1 核心逻辑
// 检测当前页面是否为Amazon搜索结果页
function isAmazonSearchPage() {
const hostname = window.location.hostname;
const isAmazon = SUPPORTED_DOMAINS.some(d => hostname === d);
if (!isAmazon) return false;
const path = window.location.pathname;
if (!path.startsWith('/s')) return false;
const params = new URLSearchParams(window.location.search);
return params.has('k') || params.has('keywords');
}
// 提取搜索结果中的不重复ASIN
function extractUniqueAsins() {
const asinSet = new Set();
// 只从 data-component-type="s-search-result" 容器提取
// 过滤掉广告和推荐位
const searchResults = document.querySelectorAll(
'div[data-component-type="s-search-result"]'
);
searchResults.forEach(el => {
if (!isSearchResultContainer(el)) return;
const asin = el.getAttribute('data-asin');
if (asin && /^[A-Z0-9]{10}$/.test(asin)) {
asinSet.add(asin);
}
});
return Array.from(asinSet);
}
一个重要的细节:只从 data-component-type="s-search-result" 的容器提取ASIN,这样就排除了广告、推荐位等非搜索结果。不然点开会发现打开了10个商品+6个广告。
支持12个Amazon国家站点,从北美到澳洲全覆盖。
插件3:Amazon ASIN Opener v1.0.1
这个插件是为了解决另一种场景:我手头有个ASIN列表(几十个甚至上百个),想批量导出它们的详细信息。
如果手动一个一个输入URL打开,那效率也太低了。所以这个插件的功能是------读一个包含ASIN列表的文件,自动批量打开所有商品详情页。
json
// JSON --- ASPEN Opener manifest.json
{
"manifest_version": 3,
"name": "Amazon ASIN Opener",
"version": "1.0.1",
"description": "Amazon ASIN Opener - 根据ASIN文件批量打开Amazon商品详情页面",
"permissions": ["tabs", "storage", "activeTab"],
"host_permissions": [
"https://www.amazon.com/*",
"https://www.amazon.co.jp/*",
// ... 10个Amazon站点
],
"background": {
"service_worker": "background.js",
"type": "module"
}
}
支持的文件格式:
javascript
// JavaScript --- 支持的文件解析
function parseAsinFile(content, fileType) {
const asins = new Set();
switch (fileType.toLowerCase()) {
case 'txt':
// 纯ASIN: B0G4SXD3TJ
// 也可以带引号: "B0G4SXD3TJ",
// 也可以包含URL: https://amazon.com/dp/B0G4SXD3TJ
const lines = content.split('\n');
lines.forEach(line => {
let asin = line.trim();
if (!asin) return;
// 尝试多种格式
if (/^[A-Z0-9]{10}$/.test(asin)) {
asins.add(asin);
return;
}
// 带引号的格式
const cleaned = asin.replace(/^["']|["'],?$/g, '').trim();
if (/^[A-Z0-9]{10}$/.test(cleaned)) {
asins.add(cleaned);
return;
}
// 从URL中提取
const match = asin.match(/[A-Z0-9]{10}/);
if (match) asins.add(match[0]);
});
break;
case 'csv':
// CSV文件:灵活解析
// ...
break;
}
return Array.from(asins);
}
弹出界面还提供了丰富的配置选项:
┌─────────────────────────────────────┐
│ Amazon ASIN Opener v1.0.1 │
├─────────────────────────────────────┤
│ 📂 选择ASIN文件 │
│ ┌─────────────────────────────┐ │
│ │ 拖放文件到这里,或点击 │ │
│ │ [📂 选择文件] │ │
│ └─────────────────────────────┘ │
│ 支持: .txt, .csv, .json │
│ │
│ ⚙️ 配置选项 │
│ Amazon域名: [com ▼] │
│ 打开间隔: [1000 ] ms │
│ 最大并发: [5 ] │
│ □ 完成后自动关闭标签页 │
│ │
│ [▶ 开始打开] [⏹ 停止] │
│ │
│ 📊 进度: 12/50 ASIN │
│ ✅ 成功: 10 ❌ 失败: 2 │
└─────────────────────────────────────┘
可以设置打开间隔(防止Amazon检测到批量操作)、最大并发标签页数、完成后是否自动关闭等。
完整工作流
4个插件组合起来使用:
场景1:快速调研一个品类
在Amazon搜索 "electric bike"
→ 点击"搜索页提取器" → 拿到当前页所有商品信息
→ 或者点击"Search Opener" → 自动打开所有商品详情页
→ 在每个详情页点击"商品详情提取器" → 拿到完整数据
场景2:批量分析已有ASIN列表
拿到一个包含100个ASIN的文件
→ ASIN Opener 读取文件 → 自动打开100个详情页
→ 每个打开页面自动触发提取(auto_extract.js)
→ 所有数据自动保存
场景3:多站点对比
把ASIN列表分别用不同站点的ASIN Opener打开
→ 对比美亚、日亚、德亚的同一产品的价格差异
最终验证
经过多轮迭代,最终收集了 77个产品 的完整数据,保存为CSV和XLSX格式,12个字段:
| 字段 | 说明 |
|---|---|
| ASIN | Amazon标准识别码 |
| 标题 | 产品全称 |
| 链接 | 产品详情页URL |
| 价格 | 当前售价 |
| 评分 | 用户评分(1-5) |
| 评价数 | 累计评价数量 |
| 品牌 | 品牌/制造商 |
| 图片 | 产品主图URL |
| 描述 | 产品描述 |
| 卖点 | feature-bullets |
| 分类 | 所属品类 |
| 上架时间 | 首次上架日期 |
整个插件矩阵的开发成果对比:
| 插件 | 版本 | 功能 | 支持站点 |
|---|---|---|---|
| 商品详情提取器 | v1.1.0 | 提取单个商品全部详情 | 9个 |
| 搜索结果提取器 | v1.2.0 | 一键提取搜索页所有商品 | 18个 |
| Search Opener | v1.4.7 | 搜索页检测ASIN→批量打开详情 | 12个 |
| ASIN Opener | v1.0.1 | 文件读ASIN列表→批量打开 | 10个 |
版本迭代记录
从插件诞生到最终成熟,备份文件记录了这个过程:
# 商品详情提取器迭代
Amazon_Product_Extractor_Backup_v1.0.40_20260420_125027.zip
Amazon_Product_Extractor_Backup_v1.0.40_20260427_175609.zip
Amazon_Product_Extractor_Backup_v1.1.0_20260429_164920.zip
# Search Opener 迭代
amazon_search_opener_backup_20260427_114547
amazon_search_opener_backup_20260427_145432
amazon_search_opener_backup_20260427_151156
amazon_search_opener_backup_20260427_152137
amazon_search_opener_backup_20260427_153935
amazon_search_opener_backup_20260427_155507
# ASIN Opener 备份
Amazon_ASIN_Opener_Backup_v1.0.1_20260419_2049
# 搜索结果提取器备份
amazon_search_extractor_backup_20260427_114547
amazon_search_extractor_backup_20260427_145432
amazon_search_extractor_backup_20260427_151156
一天之内备份了6次Search Opener,说明那天应该是在不停地改bug、调参数。从v1.0.40一路迭代到v1.1.0,每次大版本都意味着功能质变。
总结
1. Amazon的反爬虫到底有多强?
非常强。 不是说"有点难度"那种强,是"你换个品类试试红茶都不行"那种强。
根据折腾的经验,Amazon的防护体系大概是这样的:
检测层级:
┌─────────────────────────────────────────┐
│ 第1层:IP信誉度 │
│ (我的IP被标记后,所有请求都触发验证码) │
├─────────────────────────────────────────┤
│ 第2层:TLS指纹检测 │
│ (不同HTTP库的TLS握手特征可以被识别) │
├─────────────────────────────────────────┤
│ 第3层:HTTP特征分析 │
│ (User-Agent、Headers、Accept-Language)│
├─────────────────────────────────────────┤
│ 第4层:行为模式分析 │
│ (鼠标轨迹、滚动速度、点击间隔) │
├─────────────────────────────────────────┤
│ 第5层:验证码(最终防线) │
│ (Amazon的验证码系统非常敏感) │
└─────────────────────────────────────────┘
普通个人开发者,没有专门的代理网络和指纹伪装技术,基本不要想自动化抓取Amazon。
2. 如果非要做,路线图是什么?
方案A:自动化爬虫 ❌
成本:低(几行代码)
成功率:0%(个人IP被标记后)
推荐度:不推荐
方案B:Chrome插件矩阵 ✅(本文方案)
成本:中(数天开发 + 多轮迭代)
成功率:100%(人工操作)
缺点:不能纯自动化,需要人看着
推荐度:适合个人/小批量
方案C:第三方数据源(如 Keepa、Jungle Scout)
成本:高(月费 $30-$100+)
成功率:高
推荐度:商用推荐
方案D:代理网络 + 指纹浏览器
成本:高(代理 + 工具)
成功率:中(需要持续对抗)
推荐度:不推荐个人折腾
3. 写Chrome插件的一些教训
- manifest.json的权限声明不能漏 ---
notifications、downloads、scripting这些都要提前加上,API没权限就给你 undefined - Service Worker 会休眠 --- Manifest V3 的 background script 不是常驻的,需要心跳保活
- 多选择器兜底 --- Amazon页面结构经常微调,不要依赖单一选择器
- URL匹配要覆盖全面 --- Amazon不同站点的URL格式不一样(/dp/、/gp/product/),content_scripts 的 matches 要写全
- 提取函数需要重试机制 --- 页面没加载完就执行脚本,取到的数据是空的
- 一个插件解决一个问题 --- 把功能拆分成多个插件,比一个大而全的插件更容易维护和迭代
- 文件解析要灵活 --- ASIN可能来自纯文本文件、CSV、甚至带引号和逗号的格式,解析器要做好各种兼容
4. 终极感悟
这个项目虽然最终没有实现自动化抓取,但收获其实不少:
- 搞清楚了 Amazon 反爬虫到底有多猛(以后不用再试了)
- 学会了 Chrome 扩展开发,从 Manifest V3 入门到精通
- 从1个插件扩展到4个插件的完整工具矩阵
- 从单页提取进化到批量流水线操作
- 积累了选择器兜底、文件解析、多站点支持等实用经验
- 最终77个产品的数据分析用在了市场报告里,项目的目标还是达成了
过程虽然曲折,但结果不坏。
而且,折腾完这一轮之后我发现:手动 + 插件的组合方式,其实比全自动更灵活。遇到页面结构变化?不用改代码,人眼自动适应。遇到价格变动?人可以凭经验判断是否异常。有些时候,人的判断力比自动化脚本可靠得多。
项目周期: 2026-04-08 至 2026-04-29(含后续迭代)
最终成果:
| 项目 | 价值 |
|---|---|
| Amazon商品详情提取器 v1.1.0 | 单个产品完整信息提取 |
| Amazon搜索结果提取器 v1.2.0 | 搜索页批量提取(18个站点) |
| Amazon Search Opener v1.4.7 | 搜索页ASIN检测+批量打开 |
| Amazon ASIN Opener v1.0.1 | 文件批量打开ASIN详情页 |
| 产品数据样本 | 77个ASIN,12个字段 |
| 技术文档 | 完整的开发文档和使用指南 |
一句话总结: 自动化被Amazon拍死在地上,但我用4个Chrome插件搭了一套流水线,手动操作的效率提升了至少20倍。