[关闭]
@hhlf282 2026-03-20T01:03:22.000000Z 字数 7287 阅读 17

Daraz 数据爬取方案

目标: 爬取 Daraz 斯里兰卡站点的商品数据,用于 AI 选品训练
版本: 1.0
创建时间: 2026-03-19


1. 爬取目标

1.1 数据范围

数据类型 字段 更新频率 优先级
商品信息 标题、价格、销量、评价、图片、类目 每日 P0
卖家信息 店铺名、评分、粉丝数、店铺等级 每周 P1
评论数据 评论内容、评分、时间、图片 每周 P1
类目结构 类目树、子类目 每月 P2
活动信息 Flash Sale、促销活动 每日 P1

1.2 目标数据量

阶段 商品数量 类目覆盖 时间跨度
Phase 1 1,000 SKU TOP 10 类目 当前
Phase 2 10,000 SKU TOP 50 类目 3 个月历史
Phase 3 50,000 SKU 全类目 1 年历史

2. 技术选型

2.1 爬虫框架对比

框架 优点 缺点 选择
Scrapy 高性能、异步、扩展性好 学习曲线陡 ✅ 主力
Playwright 支持 JS 渲染、反爬绕过 资源消耗大 ✅ 补充
Selenium 简单易用 速度慢、易检测
Requests 轻量 无 JS 支持

2.2 技术栈

  1. 爬虫框架:Scrapy + Playwright
  2. 代理 IPBright Data / Oxylabs
  3. 数据存储:PostgreSQL + MongoDB
  4. 任务调度:Airflow
  5. 监控告警:Prometheus + Grafana

3. 爬取策略

3.1 类目遍历

  1. # Daraz 斯里兰卡站点类目结构
  2. BASE_URL = "https://www.daraz.lk"
  3. CATEGORIES = [
  4. {"id": "10000312", "name": "Fashion", "subcategories": [...]},
  5. {"id": "10000574", "name": "Electronics", "subcategories": [...]},
  6. {"id": "10000339", "name": "Home & Living", "subcategories": [...]},
  7. {"id": "10000663", "name": "Health & Beauty", "subcategories": [...]},
  8. {"id": "10000336", "name": "Baby & Toys", "subcategories": [...]},
  9. # ... 共 50+ 一级类目
  10. ]

3.2 分页策略

  1. # Daraz 列表页分页规则
  2. # https://www.daraz.lk/some-category/?page=1&pageSize=40
  3. MAX_PAGES = 50 # 每个类目最多爬 50 页
  4. PAGE_SIZE = 40 # 每页 40 个商品
  5. ITEMS_PER_CATEGORY = MAX_PAGES * PAGE_SIZE # 2000 个商品/类目

3.3 商品详情爬取

  1. # 商品详情页 URL 规则
  2. # https://www.daraz.lk/products/product-name-i{item_id}.html
  3. # 需要提取的字段
  4. PRODUCT_FIELDS = {
  5. "item_id": "string", # 商品 ID
  6. "title": "string", # 标题
  7. "price": "float", # 当前价格 (LKR)
  8. "original_price": "float", # 原价 (LKR)
  9. "discount": "float", # 折扣比例
  10. "currency": "string", # 货币 (LKR)
  11. "category_id": "string", # 类目 ID
  12. "category_name": "string", # 类目名称
  13. "brand": "string", # 品牌
  14. "seller_id": "string", # 卖家 ID
  15. "seller_name": "string", # 卖家名称
  16. "rating": "float", # 评分 (0-5)
  17. "review_count": "int", # 评价数量
  18. "sold_count": "int", # 销量
  19. "stock_status": "string", # 库存状态
  20. "images": "list[string]", # 图片 URL 列表
  21. "description": "string", # 商品描述
  22. "specifications": "dict", # 规格参数
  23. "shipping_fee": "float", # 运费
  24. "delivery_time": "string", # 配送时间
  25. "return_policy": "string", # 退换政策
  26. "crawl_time": "datetime", # 爬取时间
  27. }

4. 反爬策略

4.1 风险等级

行为 风险 建议频率
访问列表页 1 请求/秒
访问详情页 1 请求/2 秒
访问评论页 1 请求/2 秒
批量爬取 需代理 IP

4.2 反爬措施

  1. # 1. User-Agent 轮换
  2. USER_AGENTS = [
  3. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...",
  4. "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
  5. # ... 50+ 个 User-Agent
  6. ]
  7. # 2. 代理 IP 池
  8. PROXY_PROVIDERS = [
  9. "brightdata.com",
  10. "oxylabs.io",
  11. # 预算有限可用免费代理 (不推荐生产环境)
  12. ]
  13. # 3. 请求频率控制
  14. DOWNLOAD_DELAY = 2 # 2 秒间隔
  15. CONCURRENT_REQUESTS = 8 # 并发 8 个
  16. # 4. Cookie 管理
  17. COOKIES_ENABLED = True
  18. COOKIES_DEBUG = False
  19. # 5. 随机等待
  20. RANDOMIZE_DOWNLOAD_DELAY = True

4.3 异常处理

  1. # 常见状态码处理
  2. STATUS_CODE_HANDLING = {
  3. 200: "正常处理",
  4. 301: "跟随重定向",
  5. 302: "跟随重定向",
  6. 403: "被封禁,切换 IP",
  7. 404: "商品下架,记录",
  8. 429: "请求过多,等待重试",
  9. 500: "服务器错误,等待重试",
  10. 503: "服务不可用,等待重试",
  11. }
  12. # 重试机制
  13. RETRY_TIMES = 3
  14. RETRY_HTTP_CODES = [429, 500, 502, 503, 504]

5. 数据存储

5.1 数据库设计

  1. -- 商品表
  2. CREATE TABLE products (
  3. id SERIAL PRIMARY KEY,
  4. item_id VARCHAR(50) UNIQUE NOT NULL,
  5. title VARCHAR(500) NOT NULL,
  6. price DECIMAL(10,2),
  7. original_price DECIMAL(10,2),
  8. discount DECIMAL(5,2),
  9. currency VARCHAR(3) DEFAULT 'LKR',
  10. category_id VARCHAR(50),
  11. category_name VARCHAR(200),
  12. brand VARCHAR(200),
  13. seller_id VARCHAR(50),
  14. seller_name VARCHAR(200),
  15. rating DECIMAL(3,2),
  16. review_count INTEGER DEFAULT 0,
  17. sold_count INTEGER DEFAULT 0,
  18. stock_status VARCHAR(50),
  19. images JSONB,
  20. description TEXT,
  21. specifications JSONB,
  22. shipping_fee DECIMAL(10,2),
  23. delivery_time VARCHAR(100),
  24. return_policy TEXT,
  25. crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  26. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  27. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  28. );
  29. -- 价格历史表 (用于价格趋势分析)
  30. CREATE TABLE price_history (
  31. id SERIAL PRIMARY KEY,
  32. item_id VARCHAR(50) NOT NULL,
  33. price DECIMAL(10,2) NOT NULL,
  34. original_price DECIMAL(10,2),
  35. discount DECIMAL(5,2),
  36. crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  37. FOREIGN KEY (item_id) REFERENCES products(item_id)
  38. );
  39. -- 销量历史表 (用于销量趋势分析)
  40. CREATE TABLE sales_history (
  41. id SERIAL PRIMARY KEY,
  42. item_id VARCHAR(50) NOT NULL,
  43. sold_count INTEGER NOT NULL,
  44. crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  45. FOREIGN KEY (item_id) REFERENCES products(item_id)
  46. );
  47. -- 评论表
  48. CREATE TABLE reviews (
  49. id SERIAL PRIMARY KEY,
  50. item_id VARCHAR(50) NOT NULL,
  51. review_id VARCHAR(50) UNIQUE,
  52. user_name VARCHAR(200),
  53. rating INTEGER CHECK (rating >= 1 AND rating <= 5),
  54. comment TEXT,
  55. images JSONB,
  56. helpful_count INTEGER DEFAULT 0,
  57. crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  58. FOREIGN KEY (item_id) REFERENCES products(item_id)
  59. );
  60. -- 创建索引
  61. CREATE INDEX idx_products_category ON products(category_id);
  62. CREATE INDEX idx_products_seller ON products(seller_id);
  63. CREATE INDEX idx_products_price ON products(price);
  64. CREATE INDEX idx_products_rating ON products(rating);
  65. CREATE INDEX idx_products_sold ON products(sold_count);
  66. CREATE INDEX idx_price_history_time ON price_history(crawl_time);
  67. CREATE INDEX idx_sales_history_time ON sales_history(crawl_time);

5.2 数据导出

  1. # 导出为 AI 训练格式
  2. def export_for_training():
  3. """
  4. 导出为 JSONL 格式,用于 AI 模型训练
  5. """
  6. query = """
  7. SELECT
  8. p.item_id,
  9. p.title,
  10. p.category_name,
  11. p.price,
  12. p.sold_count,
  13. p.rating,
  14. p.review_count,
  15. s.avg_price as avg_category_price,
  16. s.avg_sales as avg_category_sales,
  17. s.competition_score
  18. FROM products p
  19. LEFT JOIN (
  20. SELECT
  21. category_id,
  22. AVG(price) as avg_price,
  23. AVG(sold_count) as avg_sales,
  24. COUNT(DISTINCT seller_id) / COUNT(DISTINCT item_id) as competition_score
  25. FROM products
  26. GROUP BY category_id
  27. ) s ON p.category_id = s.category_id
  28. WHERE p.crawl_time > NOW() - INTERVAL '30 days'
  29. """
  30. # 导出为 JSONL
  31. # 每条记录包含:商品特征 + 类目平均水平 + 竞争度

6. 部署方案

6.1 爬虫架构

  1. ┌─────────────────────────────────────────────────────────┐
  2. 调度层 (Airflow)
  3. - 定时任务调度
  4. - 任务依赖管理
  5. - 失败重试
  6. └─────────────────────────────────────────────────────────┘
  7. ┌─────────────────────────────────────────────────────────┐
  8. 爬虫层 (Scrapy)
  9. - 类目爬虫 (CategorySpider)
  10. - 商品爬虫 (ProductSpider)
  11. - 评论爬虫 (ReviewSpider)
  12. └─────────────────────────────────────────────────────────┘
  13. ┌─────────────────────────────────────────────────────────┐
  14. 存储层 (PostgreSQL)
  15. - 商品数据
  16. - 价格历史
  17. - 销量历史
  18. - 评论数据
  19. └─────────────────────────────────────────────────────────┘

6.2 Docker 部署

  1. # Dockerfile
  2. FROM python:3.11-slim
  3. WORKDIR /app
  4. # 安装依赖
  5. COPY requirements.txt .
  6. RUN pip install -r requirements.txt
  7. # 复制代码
  8. COPY . .
  9. # 设置环境变量
  10. ENV PYTHONUNBUFFERED=1
  11. ENV SCRAPY_SETTINGS_MODULE=daraz_spider.settings
  12. # 运行爬虫
  13. CMD ["scrapy", "crawl", "product_spider"]
  1. # docker-compose.yml
  2. version: '3.8'
  3. services:
  4. postgres:
  5. image: postgres:15
  6. environment:
  7. POSTGRES_DB: daraz
  8. POSTGRES_USER: daraz_user
  9. POSTGRES_PASSWORD: ${DB_PASSWORD}
  10. volumes:
  11. - postgres_data:/var/lib/postgresql/data
  12. ports:
  13. - "5432:5432"
  14. spider:
  15. build: .
  16. environment:
  17. DATABASE_URL: postgresql://daraz_user:${DB_PASSWORD}@postgres:5432/daraz
  18. PROXY_API_KEY: ${PROXY_API_KEY}
  19. depends_on:
  20. - postgres
  21. deploy:
  22. replicas: 3 # 3 个爬虫实例
  23. airflow:
  24. image: apache/airflow:2.7.0
  25. environment:
  26. - AIRFLOW__CORE__EXECUTOR=LocalExecutor
  27. volumes:
  28. - ./airflow/dags:/opt/airflow/dags
  29. ports:
  30. - "8080:8080"
  31. depends_on:
  32. - postgres
  33. volumes:
  34. postgres_data:

7. 监控与告警

7.1 监控指标

指标 阈值 告警方式
爬取成功率 <90% Slack 通知
请求失败率
10%
Slack 通知
IP 被封率
5%
邮件 + Slack
数据量异常 < 预期 50% Slack 通知
数据库连接 失败 邮件 + Slack

7.2 日志记录

  1. # 日志配置
  2. LOGGING = {
  3. 'version': 1,
  4. 'handlers': {
  5. 'file': {
  6. 'class': 'logging.FileHandler',
  7. 'filename': 'logs/spider.log',
  8. },
  9. 'slack': {
  10. 'class': 'slack_handler.SlackHandler',
  11. 'webhook_url': '${SLACK_WEBHOOK}',
  12. 'level': 'ERROR',
  13. },
  14. },
  15. 'loggers': {
  16. 'daraz_spider': {
  17. 'handlers': ['file', 'slack'],
  18. 'level': 'INFO',
  19. },
  20. },
  21. }

8. 合规与道德

8.1 遵守规则

8.2 数据使用


9. 预算估算

项目 配置 价格
代理 IP Bright Data, 10GB/月 300/月
数据库 PostgreSQL (自建) 0
合计 - ~$800/月

预算有限方案:
- 使用免费代理 (稳定性差)
- 降低爬取频率
- 减少并发数
- 预算可降至 ~$200/月


10. 快速启动

10.1 环境准备

  1. # 1. 克隆代码
  2. git clone [repo_url]
  3. cd daraz-spider
  4. # 2. 创建虚拟环境
  5. python -m venv venv
  6. source venv/bin/activate # Linux/Mac
  7. # or
  8. venv\Scripts\activate # Windows
  9. # 3. 安装依赖
  10. pip install -r requirements.txt
  11. # 4. 配置环境变量
  12. cp .env.example .env
  13. # 编辑 .env 文件,填写数据库、代理等配置
  14. # 5. 启动数据库
  15. docker-compose up -d postgres
  16. # 6. 运行爬虫
  17. scrapy crawl product_spider

10.2 测试爬取

  1. # 测试爬取 10 个商品
  2. scrapy crawl product_spider -a limit=10
  3. # 测试爬取单个类目
  4. scrapy crawl category_spider -a category_id=10000312 -a max_pages=5
  5. # 导出测试数据
  6. scrapy crawl product_spider -o test_output.jsonl

版本: 1.0
创建时间: 2026-03-19
维护者: 技术团队

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注