Amazon反爬虫:一场从自动化到Chrome插件的折腾之旅

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个)

这个插件的功能很纯粹:在搜索结果页面检测出所有不重复的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插件的一些教训

  1. manifest.json的权限声明不能漏 --- notificationsdownloadsscripting 这些都要提前加上,API没权限就给你 undefined
  2. Service Worker 会休眠 --- Manifest V3 的 background script 不是常驻的,需要心跳保活
  3. 多选择器兜底 --- Amazon页面结构经常微调,不要依赖单一选择器
  4. URL匹配要覆盖全面 --- Amazon不同站点的URL格式不一样(/dp/、/gp/product/),content_scripts 的 matches 要写全
  5. 提取函数需要重试机制 --- 页面没加载完就执行脚本,取到的数据是空的
  6. 一个插件解决一个问题 --- 把功能拆分成多个插件,比一个大而全的插件更容易维护和迭代
  7. 文件解析要灵活 --- 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倍。

相关推荐
weedsfly2 小时前
前端开发中的代理模式——从 Vue 3 响应式到日常开发
前端·javascript·面试
Li.map2 小时前
CesiumJS 地图主题系统:用着色器打造实时滤镜
javascript·arcgis·cesium·着色器
用户298698530142 小时前
在 React 中通过 JavaScript 实现 Excel 单元格、行与列的锁定保护
javascript·react.js·excel
এ慕ོ冬℘゜2 小时前
深入理解 JavaScript 事件对象:从 target 到 preventDefault 的实战指南
开发语言·前端·javascript
Listen·Rain2 小时前
Vue概述
前端·javascript·vue.js
小雪_Snow3 小时前
JS 数组的遍历 —— 两种方式详解
前端·javascript
小二·3 小时前
WebGPU 浏览器端跑大模型:让AI在网页里跑起来(WebLLM/Transformers.js实战)
开发语言·javascript·人工智能
心中有国也有家3 小时前
AtomGit Flutter 鸿蒙客户端:零外部资源的应用打包策略
android·javascript·flutter·华为·harmonyos
胡萝卜术12 小时前
从API调用到手写LRU:力扣146「LRU缓存」的哈希表+双向链表终极进化之路
前端·javascript·面试