Skip to content

ElijahRRR/amazon-scraper-v2

Repository files navigation

Amazon Product Scraper v2

高性能 Amazon 商品数据采集系统。采用分布式架构,支持多 Worker 并行采集,通过 TLS 指纹模拟和隧道代理实现稳定的反反爬。

系统架构

┌─────────────────────────────────────────────────────┐
│                   Web UI (浏览器)                      │
│   仪表盘 / 任务管理 / 结果浏览 / 设置 / Worker 监控    │
└───────────────────────┬─────────────────────────────┘
                        │ HTTP
┌───────────────────────▼─────────────────────────────┐
│              Server (FastAPI :8899)                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐   │
│  │ 任务分发  │  │ 结果入库  │  │ 全局并发协调器    │   │
│  └────┬─────┘  └────▲─────┘  │ 预算分配+封锁传播 │   │
│       │             │        └────────┬─────────┘   │
│  ┌────▼─────────────┴────┐   ┌───────▼──────────┐   │
│  │   SQLite (WAL+5s锁)   │   │ 定时采集调度器    │   │
│  │  tasks + results 表   │   │ 多任务时间点触发   │   │
│  └───────────────────────┘   └──────────────────┘   │
└───────────────────────┬─────────────────────────────┘
                        │ REST API (含配额分配)
         ┌──────────────┼──────────────┐
         │              │              │
┌────────▼───┐  ┌───────▼────┐  ┌─────▼──────┐
│  Worker 1  │  │  Worker 2  │  │  Worker N  │
│ curl_cffi  │  │ curl_cffi  │  │ curl_cffi  │
│ 截图:开启   │  │ 截图:关闭   │  │ 截图:关闭   │
│     │ HTML │  └──────┬─────┘  └──────┬─────┘
│  ┌──▼────┐ │         │               │
│  │截图子 │ │         └───────┼───────┘
│  │进程   │ │                 │
│  │Playw. │ │        ┌────────▼────────┐
│  └───────┘ │        │   快代理 TPS     │
└────────────┘        │   隧道代理       │
                      │  (自动换 IP)     │
                      └────────┬────────┘
                               │
                      ┌────────▼────────┐
                      │   Amazon.com    │
                      └─────────────────┘

数据模型(ASIN 主表模式)

系统采用 ASIN 主表模式results 表以 ASIN 为唯一索引,每个 ASIN 始终只有一行数据(最新状态)。

  • tasks = 任务层(批次管理,跟踪采集进度)
  • results = 数据层(ASIN 主表,唯一索引 (asin),始终保留最新数据)
  • 变动字段 = 同步层(记录与上次采集的差异方向 + 增量游标)

关键行为:

  • 同一 ASIN 被多次采集时,ON CONFLICT(asin) DO UPDATE 原地更新,自动对比变动
  • "批次"代表"成员集合"——按批次筛选时看到的是该批次 ASIN 的当前最新数据
  • 按批次筛选通过 EXISTS(tasks...) 实现(不用 JOIN,无重复行)
  • 删除批次只删 tasks + 截图文件 + 清空悬空 screenshot_path,不删 results
  • 删除 ASIN 数据需通过 DELETE /api/results 显式操作

变动追踪

每次采集自动与主表旧数据对比,记录变动方向:

变动字段 含义 取值
price_change 价格变动 up / down / 空
stock_qty_change 库存数量变动 up / down / 空
stock_status_change 库存状态变动 changed / 空
other_change 其他字段变动(content_hash) 1 / 0
is_new 是否为首次采集 1 / 0

前端在价格列显示 ↑(红色涨价)/ ↓(绿色降价),库存列显示 ↑↓ + 状态变化标记 ●,新增 ASIN 显示 NEW 徽章。

数据流

  1. 用户通过 Web UI 上传 ASIN 文件 → Server 创建采集任务入库
  2. Worker 从 Server 拉取待处理任务(/api/tasks/pull),优先任务独占队列(数据库层面隔离最高优先级)
  3. Worker 通过隧道代理向 Amazon 发起请求,解析 HTML 提取数据
  4. Worker 将采集结果批量推送回 Server(/api/tasks/result/batch
  5. Server 入库时自动与主表旧数据对比,记录价格/库存/内容变动,分配 change_seq 序号
  6. 若任务需要截图且 Worker 开启截图功能:HTML 写入磁盘 → 截图子进程渲染 → 逐张即时上传 Server → 删除 HTML
  7. 截图批次全部上传完成前,Worker 暂停拉取新任务(门控机制)
  8. 用户在 Web UI 查看进度、浏览结果(支持变动筛选)、导出 Excel/CSV/数据库文件(支持字段选择)
  9. 定时采集调度器在设定时间自动对主库所有 ASIN 发起重新采集

技术栈

组件 技术 用途
HTTP 客户端 curl_cffi (AsyncSession) TLS/JA3 指纹模拟,HTTP/2 多路复用
浏览器指纹 impersonate="chrome131" 模拟 Chrome 131 的完整 TLS 握手特征
内部 HTTP httpx (AsyncClient) Worker↔Server 通信(拉取任务、提交结果)
HTML 解析 selectolax (Lexbor) / lxml selectolax 比 lxml 快 2-5x,lxml 作 fallback
Web 框架 FastAPI + Uvicorn 异步 REST API 和 Web UI
数据库 SQLite (WAL 模式) + aiosqlite 异步读写,WAL 支持并发,busy_timeout=5s 防锁冲突
代理 快代理 TPS 隧道代理 固定入口,服务端自动换 IP
压缩 Brotli (br) 比 gzip 小 15-25%,减少传输量
模板 Jinja2 Web UI 页面渲染
导出 openpyxl / csv / SQLite Excel (.xlsx)、CSV、数据库文件导出
截图存证 Playwright (Chromium) 可选功能,渲染商品页截图用于数据抽查

反反爬策略

TLS 指纹模拟

普通 Python HTTP 库(requests/httpx/aiohttp)的 TLS 握手特征与浏览器不同,Amazon 通过 JA3 指纹检测即可识别。curl_cffi 通过 impersonate 参数完整模拟 Chrome 的 TLS 握手过程(密码套件、扩展顺序、ALPN 等),使请求在网络层面与真实浏览器无法区分。

HTTP/2 多路复用

启用 http_version=2,多个请求共享同一条 TCP+TLS 连接,减少连接建立开销,同时降低被代理端检测到多连接的风险。

Session 主动轮换

每完成 1000 次成功请求,主动关闭当前 Session 并创建新的。更换 User-Agent、重新获取代理 IP、重新初始化 Cookie,防止 Amazon 通过行为指纹(请求频率、Cookie 老化等)识别。

请求头仿真

  • 15 个真实 Chrome 131 User-Agent 轮换
  • 完整的 sec-ch-ua / sec-ch-ua-platform 客户端提示头(与 impersonate=chrome131 保持版本一致)
  • 正确的 Referer 链(首页 → 产品页)
  • 标准的 Sec-Fetch-* 头组合

邮编设置

通过 POST 请求 /gp/delivery/ajax/address-change.html 设置配送邮编,而非伪造 Cookie。这确保 Amazon 返回正确的价格和配送信息。

核心模块

config.py — 配置中心

所有可调参数集中管理。代理凭证通过环境变量注入,不硬编码在代码中。支持两种方式:

# 方式 1:环境变量
export KDL_SECRET_ID=your_secret_id
export KDL_SIGNATURE=your_signature

# 方式 2:.env 文件(自动加载,无需手动 source)
cp .env.example .env
# 编辑 .env 填入凭证

基础参数:

参数 默认值 说明
MAX_CLIENTS 32 HTTP/2 连接池大小(建议为并发数的 2 倍)
REQUEST_TIMEOUT 15s 单次请求超时(短超时更快释放并发槽位)
MAX_RETRIES 3 最大重试次数
SESSION_ROTATE_EVERY 1000 每 N 次成功请求轮换 Session
TOKEN_BUCKET_RATE 5.0 全局 QPS 上限(令牌桶速率,每秒请求数)
IMPERSONATE_BROWSER chrome131 TLS 指纹模拟目标
PROXY_REFRESH_INTERVAL 30s 代理刷新间隔

自适应并发控制参数:

参数 默认值 说明
INITIAL_CONCURRENCY 8 冷启动并发数(保守开始,自动攀升)
MIN_CONCURRENCY 4 并发下限
MAX_CONCURRENCY 16 TPS 模式并发上限
TUNNEL_MAX_CONCURRENCY 20 DPS 模式并发上限
ADJUST_INTERVAL_S 10s 评估间隔
TARGET_LATENCY_S 6.0s 目标 p50 延迟(低于此加速)
MAX_LATENCY_S 10.0s 延迟上限(超过则减速)
TARGET_SUCCESS_RATE 95% 成功率目标(高于此加速)
MIN_SUCCESS_RATE 85% 成功率下限(低于此减速)
BLOCK_RATE_THRESHOLD 5% 封锁率阈值(超过则紧急减半+冷却)
COOLDOWN_AFTER_BLOCK_S 30s 被封后冷却时间

全局并发协调参数(多 Worker 场景):

参数 默认值 说明
GLOBAL_MAX_CONCURRENCY 50 所有 Worker 总并发上限(Server 按健康度分配)
GLOBAL_MAX_QPS 4.5 所有 Worker 总 QPS 上限(Server 按健康度分配)

session.py — 会话管理

  • AmazonSession:单个采集会话,维护独立的 Cookie jar 和代理连接
    • initialize():访问首页获取 Cookie → POST 设置邮编,带 asyncio.Lock 防并发初始化 + 3 次重试
    • is_ready():检查 session 是否已初始化并可用(Worker 在处理任务前调用)
    • fetch_product_page(asin):采集商品详情页
    • is_blocked(resp):检测 403/503/验证码拦截(含页面体积阈值,避免正常产品页误判)

worker.py — 采集引擎(流水线 + 自适应并发)

分布式 Worker,可在多台机器上运行,采用流水线架构:

task_feeder → [task_queue] → worker_pool (N个协程) → [result_queue] → batch_submitter
                  ↑               │ (needs_screenshot && enable_screenshot)
       adaptive_controller        ↓
         实时调整 N          HTML→磁盘 → 截图子进程(独立PID) → 逐张上传Server
                                         ↓ _uploaded标记
                              gate_monitor → 开门放行
  • 全异步架构:Worker↔Server 通信(拉取任务、提交结果、同步设置)全部使用 httpx.AsyncClient,不阻塞 event loop
  • 流水线架构:任务补给、采集、结果提交三大协程并行,互不阻塞
  • 自适应并发:冷启动 8 并发,AIMD 算法根据延迟/成功率/封锁率自动探索最优并发数
  • 实例级参数max_retries 等运行时可调参数存储在 Worker 实例上,热同步不污染全局 config
  • 任务预取:队列低于 50% 时触发补给,保持 Worker 始终有任务可做
  • 优先任务独占:数据库 pull_tasks 先查询 MAX(priority),仅返回最高优先级任务,不混入普通任务
  • 封锁处理:检测到 403/503/验证码 → 自动轮换 Session(换 IP + 换 Cookie)
  • 主动轮换:每 1000 次成功请求主动更换 Session
  • 截图开关--no-screenshot 参数可禁用截图功能,仅采集数据不启动截图子进程
  • 启动设置全量同步:Worker 启动时自动从 Server 拉取所有运行参数(并发控制、QPS、AIMD 参数、代理地址等),远程 Worker 无需本地 .env 或环境变量
  • 全局协调同步:每 30 秒通过 POST /api/worker/sync 上报 metrics 快照 + 接收 Server 分配的并发/QPS 配额 + 检测全局封锁事件,无需重启即可热更新所有参数
  • 批量提交:结果先入队列,攒满 10 条或每 2 秒批量 POST,失败自动 3 次重试后逐条回退
  • 优雅退出:SIGINT/SIGTERM 信号处理,退出前刷新队列

screenshot_worker.py — 截图独立子进程

截图功能采用进程级隔离——采集 Worker 和截图渲染运行在两个独立的 Python 进程中,各自拥有独立的 asyncio 事件循环,彻底避免 CPU/事件循环争抢:

┌─────────────────────────┐    ┌──────────────────────────┐
│  Worker 主进程 (采集)     │    │  截图子进程 (独立 PID)     │
│  asyncio 事件循环 #1     │    │  asyncio 事件循环 #2      │
│                         │    │                          │
│  curl_cffi HTTP 请求     │    │  Playwright/Chromium 渲染  │
│  HTML 解析              │    │  渲染完立即上传 Server     │
│  ↓                      │    │  ↑                        │
│  写 HTML 到磁盘 ─────────┼──→─│  读 HTML 从磁盘            │
│                         │    │  ↓                        │
│  检查 _uploaded 标记 ←───┼──←─│  写 _uploaded 标记         │
└─────────────────────────┘    └──────────────────────────┘

截图流程(逐张即时上传):

扫描 HTML 目录 → 发现待处理文件
      ↓
并发渲染(默认 3 并发 = 1 浏览器 × 3 页面)
      ↓
等待主图加载(最多 7 秒,自动检测 Amazon 主图选择器)
      ↓
截图(1280×1300px 固定尺寸)
      ↓
立即上传到 Server(失败重试 3 次)
      ↓
上传成功 → 删除 HTML 文件
上传失败 → 保留 HTML,下轮自动重试
渲染失败 → 删除 HTML(避免无限重试)
      ↓
检查批次完成(_scraping_done 存在 + 无剩余 HTML)
      ↓
写 _uploaded 标记 → 主 Worker 门控放行

关键特性:

  • 进程隔离:采集与截图各自独立的 asyncio 事件循环 + GC,互不干扰
  • 逐张即时上传:每张截图渲染完立即上传 Server,不等待批次完成,实时可查看
  • 按需启动:仅当任务标记 needs_screenshot=True 且 Worker 开启截图功能时才启动截图子进程
  • 主图等待:截图前等待 Amazon 主图(#landingImage 等)加载完成,最多 7 秒
  • 内存回收:每渲染 200 张自动重启 Chromium 浏览器实例,防止内存泄漏导致卡死
  • 上传重试:上传失败保留 HTML 文件,下一轮扫描自动重试;渲染失败则删除 HTML 避免无限重试
  • 文件系统通信:采集完成的 HTML 写入 screenshot_cache/html/{batch}/,截图子进程监控该目录自动渲染
  • 批次门控:截图全部上传完成后写入 _uploaded 标记 → 主 Worker 检测到标记后才拉取下一批次任务
  • 固定截图尺寸:1280×1300px viewport
  • setContent() 渲染:直接将 HTML 注入 Page,无需网络导航
  • <base> 标签注入:修复协议相对 URL 在 about:blank 上下文中无法加载的问题
  • 空白截图检测:PNG < 10KB 且页面无可见内容时自动丢弃
  • 资源拦截:屏蔽 JS、字体、追踪脚本,只加载 CSS 和图片
  • 级联崩溃防护:页面级错误仅关闭当前 Page;浏览器进程崩溃才触发实例重建
  • 截图保存路径:Server 端 static/screenshots/{batch_name}/{asin}.png
  • 截图为可选功能,需安装 requirements-screenshot.txt 中的依赖

截图设置(Web UI 可调):

设置 默认值 范围 说明
截图浏览器数 1 1-10 Chromium 实例数量
单浏览器并发数 3 1-10 每个浏览器的最大并发 Page 数

总并发 = 浏览器数 × 单浏览器并发数。建议保持总并发 ≤ 6,避免 CPU/内存过载。

adaptive.py — AIMD 自适应并发控制器

类 TCP 拥塞控制算法,根据实时指标动态调整并发数:

  • Additive Increase:一切正常(成功率 ≥ 95%,p50 < 6s)→ 并发 +1
  • Multiplicative Decrease:出问题 → 并发 ÷ 2
  • 五级决策链:封锁率超标 → 成功率/延迟 → 带宽饱和 → 冷却期 → 正常加速
  • 安全 Semaphore 调整:通过重建 Semaphore 实现缩容(不操作私有 _value),并发调整加 asyncio.Lock 保护原子性
  • 冷却机制:被封后 30 秒内不加速,防止抖动
  • 抖动恢复:每个 Worker 从 Server 获得不同的恢复抖动系数(0.0~1.0),加速分支以概率 0.3 + 0.7 × jitter 决定是否 +1,防止多 Worker 同步振荡

metrics.py — 滑动窗口指标采集器

实时跟踪请求延迟、成功率、被封率、带宽使用等关键指标:

  • 30 秒滑动窗口,自动清理过期记录,使用 time.monotonic() 避免系统时钟跳变影响
  • 支持 p50/p95 延迟分位数计算(线性插值,精确计算)
  • 带宽使用率跟踪(对比代理上限)
  • 在飞请求数计数

parser.py — HTML 解析器

解析 Amazon 商品页面,提取 37 个字段:

  • 基础信息:标题、品牌、型号、制造商、原产国
  • 价格数据:原价、现价、BuyBox 价格、运费、FBA 状态
  • 库存配送:库存数量、库存状态、配送日期、配送时长
  • 分类编码:BSR 排名、类目树、UPC/EAN、父体 ASIN、变体列表
  • 规格参数:包装/商品尺寸重量、上架时间
  • 内容:五点描述、长描述、图片 URL

三层数据提取策略(稳定性优先):

JSON-LD(结构化数据)→ CSS/XPath(页面元素)→ 正则/JSON 文本
  1. JSON-LD 优先提取:从 <script type="application/ld+json"> 中提取 Schema.org Product 对象。这是 Google SEO 标准,Amazon 不会轻易改变结构,字段稳定性远高于 CSS class。
  2. CSS/XPath 补充:对于 JSON-LD 缺失或不够精确的字段(如 BuyBox 价格、FBA 状态、配送日期),使用 CSS 选择器 / XPath 从页面 DOM 提取。
  3. 正则兜底:UPC/EAN、父体 ASIN、变体列表等通过正则从页面 JS 变量中提取。

价格提取修复:

  • 限定在主商品容器内提取价格,排除推荐商品区域的价格干扰
  • 无价格 + 无 BuyBox 时库存状态返回 "N/A" 而非默认 "In Stock"

长描述 SEO 过滤:

  • 使用 re.finditer 逐段匹配,自动过滤包含 SEO 关键词("sponsored", "related", "customers also" 等)的段落
字段 优先数据源 说明
title, brand JSON-LD 最稳定,Amazon 改版不影响
current_price CSS → JSON-LD CSS 能区分 BuyBox/原价,JSON-LD 做兜底
stock_status CSS → JSON-LD CSS 有更细粒度文本,JSON-LD 只有 InStock/OutOfStock
image_urls CSS → JSON-LD CSS 从 JS 变量提取 hiRes 大图,JSON-LD 兜底
ean_list 合并 CSS 正则 + JSON-LD gtin13 合并去重

解析引擎优先使用 selectolax(基于 Lexbor C 引擎),比 lxml 快 2-5 倍。

proxy.py — 代理管理

快代理 TPS 隧道代理集成:

  • 固定隧道入口地址,IP 轮换在快代理服务端透明进行
  • 代理按需获取 + 定时过期(默认 30 秒有效期),使用 time.monotonic() 计时
  • 全异步 httpx.AsyncClient 请求 API,不阻塞 event loop
  • 被封时强制刷新,触发服务端分配新出口 IP,最多重试 3 次(指数退避)
  • 线程安全(asyncio.Lock),避免多协程同时请求 API

database.py — 数据库

SQLite WAL 模式 + busy_timeout=5000ms,两张核心表 + 计数器表:

  • tasks:采集任务队列(pending → processing → done/failed),含 error_type / error_detail 错误分类
  • results:ASIN 主表(唯一索引 (asin)),含 37 个商品字段 + 13 个变动追踪/内部字段
  • counters:全局计数器(change_seq 单调递增序号,用于增量同步)

数据库迁移(v1 → v2):

使用 PRAGMA user_version 检测版本,迁移包在显式事务内(BEGIN IMMEDIATE + COMMIT/ROLLBACK),确保原子性:

  1. 新增 13 个变动追踪列
  2. 合并重复 ASIN(按 crawl_time DESC 保留最新行)
  3. 创建 counters 计数器表
  4. 切换唯一索引:(batch_name, asin)(asin)

变动对比机制:

  • _compare_price():解析价格字符串为 float,对比返回 up/down/None
  • _compare_stock_qty():解析库存数量为 int,对比返回 up/down/None
  • _compare_stock_status():normalize + lower 对比,返回 changed/None
  • _compute_content_hash():基于稳定白名单字段(标题、品牌、分类等 24 个)计算 MD5
  • change_seq:全局单调递增序号,每次有变动时分配,未来可用于增量同步

优先级任务隔离:

pull_tasks 方法先查询 SELECT MAX(priority) FROM tasks WHERE status='pending',然后仅返回该优先级的任务。确保优先批次采集期间不会混入普通任务。

并发写入保护:

PRAGMA busy_timeout=5000 确保多 Worker 并发写入时,锁冲突会等待最多 5 秒而非立即失败,避免数据丢失。

错误分类(error_type):

error_type 触发条件 处理建议
blocked HTTP 403/503、API 封锁页面 降低并发 / 检查代理质量
captcha 验证码拦截(Robot Check) 降低 QPS / 更换代理通道
timeout 请求超时 检查网络 / 增大超时时间
parse_error 页面为空、解析失败、标题为空、非美国价格 检查邮编设置 / 页面结构变化
network 连接异常、DNS 解析失败等 检查代理连通性

关键机制:

  • 任务拉取为原子操作(BEGIN IMMEDIATE 写锁 + SELECT + UPDATE 同一事务,防并发重复分发)
  • 批量创建任务使用 executemany 高效插入
  • 结果保存使用 INSERT ... ON CONFLICT(asin) DO UPDATE,自动对比变动并更新
  • screenshot_path 使用 COALESCE(NULLIF(...)) 保护,新值为空时保留旧截图路径
  • 超时回退:processing 超过 5 分钟自动回退为 pending(防 Worker 崩溃丢任务)
  • 失败重试:支持按批次重试所有失败任务
  • 全局单例通过 asyncio.Lock 保证并发安全初始化

models.py — 数据模型

Result dataclass 定义 50 个字段:

  • 37 个商品数据字段(与 Amazon 页面字段对应)
  • 10 个变动追踪字段(price_change, stock_qty_change, prev_*, is_new, updated_at 等)
  • 3 个内部字段(content_hash, last_change_at, change_seq,不对用户导出)

导出相关常量:

  • RESULT_FIELDS:所有字段列表(存储用)
  • _INTERNAL_FIELDS:内部字段集合(content_hash, last_change_at, change_seq
  • EXPORTABLE_FIELDS:导出可选字段 = RESULT_FIELDS - _INTERNAL_FIELDS + 虚拟字段 total_price

server.py — API 服务

FastAPI 应用(lifespan 上下文管理生命周期),提供 REST API 和 Web UI:

安全机制:

  • 上传文件类型白名单(仅允许 .xlsx/.xls/.csv/.txt
  • 批次名白名单净化(只允许字母、数字、_-,防路径穿越)
  • 截图路径使用 os.path.realpath() 越界检测,防止目录遍历攻击
  • Worker 注册表自动清理:超过 10 分钟无心跳的 Worker 定时移除,防止无限增长
  • 导出字段白名单校验:仅接受 EXPORTABLE_FIELDS 中的合法字段名

全局并发协调(多 Worker 场景):

Server 端维护全局并发协调器,解决多 Worker 并发失控问题:

Worker A ──POST metrics──→ Server ──分配配额──→ Worker A (max_c=15, qps=2.0)
Worker B ──POST metrics──→ Server ──分配配额──→ Worker B (max_c=10, qps=1.5)
Worker C ──POST metrics──→ Server ──分配配额──→ Worker C (max_c=5,  qps=1.0)
                            ↑
                    全局预算 = 50 并发 / 4.5 QPS
                    按健康度加权分配
  • 全局预算分配GLOBAL_MAX_CONCURRENCYGLOBAL_MAX_QPS 定义总上限,Server 按 Worker 的成功率和封锁率加权分配配额
  • 封锁传播:任一 Worker 上报封锁率 > 5% → 触发全局冷却,所有 Worker 在下次 sync 时同步减半并发
  • 抖动恢复:每个 Worker 获得不同的恢复抖动系数(0.0~1.0),恢复时以不同概率加速,避免同步振荡
  • 向后兼容:单 Worker 模式获得 100% 预算;旧版 Server 无 /api/worker/sync 时 Worker 自动降级为 GET /api/settings

可通过 GET /api/coordinator 查看实时协调状态(总预算、已分配、每个 Worker 的配额和 metrics)。

运行时设置热同步:

通过 Web UI 的「设置」页面可实时修改以下参数,Worker 每 30 秒自动同步更新(无需重启):

  • 基础:邮编、最大重试、代理地址、Session 轮换频率
  • 截图:浏览器实例数、单浏览器并发数
  • 速率与并发:全局总并发上限、全局总 QPS 上限、单 Worker QPS(令牌桶速率)、初始/最小/最大并发
  • AIMD 调控:评估间隔、目标延迟、延迟上限、目标成功率、成功率下限、封锁率阈值、冷却时间

设置使用版本号增量同步——Server 每次更新 _settings_version 递增,Worker 对比版本号跳过无变化的轮询。

定时自动采集:

支持配置多个每日定时采集任务,每个任务指定 HH:MM 时间点:

  • 调度器每 60 秒检查一次,当前时间 ≥ 设定时间且当天未执行 → 触发采集
  • 自动对主库所有 ASIN 创建 auto_* 批次
  • 防重叠:有未完成的 auto 批次时跳过
  • 通过 /api/auto-scrape/schedules 端点管理(增删改查)
  • 设置页面提供可视化管理界面

API 端点:

方法 路径 功能
任务管理
POST /api/upload 上传 ASIN 文件(Excel/CSV/TXT,白名单类型校验)
GET /api/tasks/pull Worker 拉取待处理任务(优先级隔离)
POST /api/tasks/result Worker 提交单条结果
POST /api/tasks/result/batch Worker 批量提交结果(单次 commit,含变动对比)
POST /api/tasks/screenshot Worker 上传截图(multipart/form-data,逐张上传)
POST /api/tasks/release Worker 归还未处理任务(优先采集切换时防丢失)
进度与批次
GET /api/progress 获取总体进度
GET /api/progress/{batch} 获取批次进度
GET /api/batches 获取批次列表
GET /api/batches/{batch}/errors 查看失败任务错误分类统计与详情
POST /api/batches/{batch}/retry 重试失败任务
POST /api/batches/{batch}/prioritize 将批次设为优先采集
DELETE /api/batches/{batch} 删除批次(仅删 tasks,保留 results,清理截图)
结果查询
GET /api/results 分页查询结果(支持批次 EXISTS 筛选 + 变动筛选 + 搜索)
DELETE /api/results 显式删除 ASIN 数据(含截图清理,不影响 tasks 历史)
导出
GET /api/export/fields 获取可导出字段列表(EXPORTABLE_FIELDS)
GET /api/export/all 全局导出 Excel/CSV(支持 change_filter + fields 参数)
GET /api/export/all/db 全局导出为独立 SQLite 文件
GET /api/export/{batch} 批次导出 Excel/CSV(支持 change_filter + fields 参数)
GET /api/export/{batch}/db 批次导出为独立 SQLite 文件(EXISTS 筛选)
GET /api/export/{batch}/screenshots 批量下载截图(ZIP 压缩包)
Worker 管理
GET /api/workers 查看在线 Worker
DELETE /api/workers 清理所有离线 Worker
DELETE /api/workers/{id} 移除指定 Worker
POST /api/worker/sync Worker 综合同步(metrics + 配额 + 全局封锁)
GET /api/coordinator 查看全局并发协调状态
GET /api/diagnostic 诊断信息(调试用)
GET /api/worker/download 下载 Worker 安装包(ZIP,含启动脚本)
设置
GET /api/settings 读取运行时设置
PUT /api/settings 修改运行时设置(带版本号增量同步 + 类型校验)
POST /api/settings/reset 恢复所有设置为默认值
定时采集
GET /api/auto-scrape/schedules 获取定时采集任务列表
POST /api/auto-scrape/schedules 新增定时采集任务(HH:MM 格式)
PUT /api/auto-scrape/schedules/{index} 更新定时任务(启用/禁用/修改时间)
DELETE /api/auto-scrape/schedules/{index} 删除定时任务
数据管理
DELETE /api/database 清空所有数据(tasks + results + 截图文件)

Web UI 页面:

路径 页面 功能
/ 仪表盘 总览进度、活跃 Worker、实时速度
/tasks 任务管理 上传 ASIN、查看批次、错误分类详情、优先采集、截图下载
/results 结果浏览 分页查看、搜索、变动筛选(全部/价格库存变动/其他变动/未变动/新增)、导出字段选择 Modal
/settings 设置 邮编、速率、并发、截图、AIMD 参数、定时采集管理(多任务时间点)
/workers Worker 监控 在线状态、统计、下载 Worker 包、清理离线

快速开始

部署

环境要求

  • Python 3.10+
  • pip

安装

cd /path/to/amazon-scraper-v2
python -m venv .venv
source .venv/bin/activate    # Linux/Mac
# .venv\Scripts\activate     # Windows
pip install -r requirements.txt

配置代理凭证

# 推荐:通过环境变量注入(不修改代码)
export KDL_SECRET_ID=your_secret_id
export KDL_SIGNATURE=your_signature

或复制 .env.example.env 并填入凭证。系统启动时自动加载 .env 文件(优先使用 python-dotenv,未安装时自动解析)。

启动服务

# 启动中央服务器
python server.py
# 服务器运行在 http://0.0.0.0:8899

启动 Worker

# 本机启动 Worker(连接本机服务器,默认开启截图功能)
python worker.py --server http://127.0.0.1:8899

# 指定参数
python worker.py --server http://192.168.1.100:8899 \
  --concurrency 10 \
  --zip-code 10001 \
  --worker-id my-worker-1

# 禁用截图功能(仅采集数据,不启动截图子进程)
python worker.py --server http://127.0.0.1:8899 --no-screenshot

Worker 只需以下文件即可独立运行(不需要完整项目):

worker.py, screenshot_worker.py, config.py, models.py, proxy.py, session.py, parser.py, metrics.py, adaptive.py
requirements-worker.txt(精简依赖,pip install -r requirements-worker.txt)
requirements-screenshot.txt(可选,截图功能需要 playwright)

Web UI 一键下载 Worker

最简单的方式——在 Server 的 Web UI 上下载 Worker 安装包:

  1. 打开浏览器访问 Server 地址(如 http://192.168.1.100:8899
  2. 进入「设置」或「Worker 监控」页面,点击「下载 Worker 安装包」
  3. 解压 ZIP 文件,双击 start.sh(macOS/Linux)或 start.bat(Windows)
  4. 启动脚本会自动创建虚拟环境、安装依赖、连接到 Server

安装包内含 8 个 Python 文件 + 依赖清单 + 启动脚本,Server 地址已自动注入。首次启动会自动创建虚拟环境、安装依赖并下载 Playwright Chromium 用于截图功能。无需配置任何环境变量——Worker 启动时会自动从 Server 拉取全部运行参数(代理地址、并发控制、QPS 限速、AIMD 调控参数等),完全由 Server 统一管理。

Worker 命令行参数:

参数 默认值 说明
--server (必填) 中央服务器地址
--worker-id 自动生成 Worker 唯一标识
--concurrency 16 最大并发上限(自适应控制器自动探索最优值)
--zip-code 10001 配送邮编
--no-screenshot 默认开启 禁用截图功能(仅采集数据,不启动截图子进程)

使用流程

  1. 打开浏览器访问 http://localhost:8899
  2. 进入「任务管理」页面,上传包含 ASIN 的 Excel/CSV/TXT 文件(可勾选「需要截图」)
  3. 启动 Worker(可在多台机器上部署)
  4. 在「仪表盘」查看实时采集进度和速度
  5. 在「结果浏览」页面查看、搜索采集数据
    • 使用变动筛选下拉框过滤:价格/库存变动、其他变动、未变动、新增 ASIN
    • 价格列显示 ↑(涨价红色)/ ↓(降价绿色),库存列显示变动标记
  6. 点击「导出」按钮,在弹出的 Modal 中选择:
    • 导出格式:Excel (.xlsx) / CSV (.csv) / 数据库 (.db)
    • 字段选择:勾选需要导出的字段(支持全选/仅价格库存等快捷操作,选择记忆到 localStorage)
    • 当前的批次筛选和变动筛选条件会自动继承到导出
    • 数据库格式始终导出全字段(包含内部字段)
    • 未选择批次时可全局导出所有 ASIN 数据
  7. 截图批次可在任务管理页面下载 ZIP 压缩包
  8. 在「设置」页面配置定时采集:
    • 点击「新增」添加定时任务,通过下拉框选择时/分
    • 支持多个时间点,每天到点自动对主库所有 ASIN 发起重新采集
    • 可单独启用/禁用/删除每个定时任务

ASIN 文件格式

支持三种格式(均自动验证格式 ^B[0-9A-Z]{9}$):

  • Excel (.xlsx / .xls):系统自动扫描所有单元格,提取合法 ASIN
  • CSV (.csv):扫描所有字段
  • 纯文本 (.txt):每行一个 ASIN

云端部署注意事项

项目 说明
代理白名单 快代理 TPS 需要绑定服务器 IP,部署后在快代理后台添加云服务器 IP
凭证安全 使用环境变量注入凭证,不要将 .env 提交到版本控制
数据库 单机 1-2 个 Worker 用 SQLite 即可;大规模多机 Worker 建议换 PostgreSQL
安全 API 无认证,公网部署建议加防火墙或 API Key
数据持久化 注意备份 data/scraper.db

性能指标

纯采集模式(1500 ASINs 全量测试)

指标 数值
采集速度 ~700 条/分钟
成功率 99.9% (1498/1500)
并发数 峰值 ~36
封锁率 0%
p50 延迟 3.2s
p95 延迟 5.8s
带宽 ~11 MB/s
总耗时 ~2 分钟

采集 + 截图模式(1500 ASINs 全量测试)

指标 数值
采集速度 ~167 条/分钟
采集耗时 ~9 分钟
截图并发 3(1 浏览器 × 3 页面)
截图尺寸 1280×1300px

截图模式下采集速度降低是因为门控机制——截图批次上传完成前 Worker 暂停拉取新任务,确保截图数据完整。采集本身的速度不受截图影响(进程隔离)。

调优历程

阶段 配置 速度 成功率
初始基准 c=5, interval=0.2s, timeout=30s ~30/min 70%
第一轮优化 c=10, interval=0.1s, session 轮换 47/min 96.6%
第二轮优化 +HTTP/2, +Chrome131, +Brotli 80/min 100%
参数调优 c=14, timeout=15s, 令牌桶 QPS=4.5 116/min 99.8%
当前版本 AIMD 自适应, 峰值 c=36 700/min 99.9%

文件结构

amazon-scraper-v2/
├── config.py              # 配置中心(凭证通过环境变量注入)
├── server.py              # FastAPI 服务端(API + Web UI + 定时采集调度器)
├── worker.py              # 采集 Worker(流水线 + 自适应并发,可多机部署)
├── screenshot_worker.py   # 截图独立子进程(逐张即时上传,内存自动回收)
├── adaptive.py            # AIMD 自适应并发控制器(类 TCP 拥塞控制)
├── metrics.py             # 滑动窗口指标采集器(延迟/成功率/带宽实时追踪)
├── session.py             # Amazon 会话管理(TLS 指纹、Cookie、邮编)
├── parser.py              # HTML 解析器(selectolax/lxml,37 个字段)
├── proxy.py               # 代理管理(快代理 TPS 隧道,全异步 httpx)
├── database.py            # 数据库操作(aiosqlite,ASIN 主表 + 变动对比 + 迁移)
├── models.py              # 数据模型(Task, Result, EXPORTABLE_FIELDS)
├── requirements.txt       # Server 完整依赖(含 httpx)
├── requirements-worker.txt # Worker 精简依赖(含 httpx)
├── requirements-screenshot.txt # 截图功能依赖(可选,playwright)
├── .env.example           # 环境变量模板(复制为 .env 并填入凭证)
├── templates/             # Web UI 模板(Jinja2)
│   ├── base.html          # 基础布局(侧边栏 + 响应式)
│   ├── dashboard.html     # 仪表盘
│   ├── tasks.html         # 任务管理
│   ├── results.html       # 结果浏览(变动筛选 + 导出字段选择 Modal)
│   ├── settings.html      # 设置(含定时采集多任务管理)
│   └── workers.html       # Worker 监控
├── screenshot_cache/      # 截图临时文件(HTML 中转 + 标记文件)
├── tests/                 # 单元测试
├── data/                  # 数据目录(SQLite 数据库文件)
└── static/                # 前端静态资源
    ├── css/style.css      # 自定义样式(CSS 变量主题)
    └── screenshots/       # 截图存证(按批次/ASIN 存储 PNG)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors