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 技术栈
爬虫框架:Scrapy + Playwright代理 IP:Bright Data / Oxylabs数据存储:PostgreSQL + MongoDB任务调度:Airflow监控告警:Prometheus + Grafana
3. 爬取策略
3.1 类目遍历
# Daraz 斯里兰卡站点类目结构BASE_URL = "https://www.daraz.lk"CATEGORIES = [ {"id": "10000312", "name": "Fashion", "subcategories": [...]}, {"id": "10000574", "name": "Electronics", "subcategories": [...]}, {"id": "10000339", "name": "Home & Living", "subcategories": [...]}, {"id": "10000663", "name": "Health & Beauty", "subcategories": [...]}, {"id": "10000336", "name": "Baby & Toys", "subcategories": [...]}, # ... 共 50+ 一级类目]
3.2 分页策略
# Daraz 列表页分页规则# https://www.daraz.lk/some-category/?page=1&pageSize=40MAX_PAGES = 50 # 每个类目最多爬 50 页PAGE_SIZE = 40 # 每页 40 个商品ITEMS_PER_CATEGORY = MAX_PAGES * PAGE_SIZE # 2000 个商品/类目
3.3 商品详情爬取
# 商品详情页 URL 规则# https://www.daraz.lk/products/product-name-i{item_id}.html# 需要提取的字段PRODUCT_FIELDS = { "item_id": "string", # 商品 ID "title": "string", # 标题 "price": "float", # 当前价格 (LKR) "original_price": "float", # 原价 (LKR) "discount": "float", # 折扣比例 "currency": "string", # 货币 (LKR) "category_id": "string", # 类目 ID "category_name": "string", # 类目名称 "brand": "string", # 品牌 "seller_id": "string", # 卖家 ID "seller_name": "string", # 卖家名称 "rating": "float", # 评分 (0-5) "review_count": "int", # 评价数量 "sold_count": "int", # 销量 "stock_status": "string", # 库存状态 "images": "list[string]", # 图片 URL 列表 "description": "string", # 商品描述 "specifications": "dict", # 规格参数 "shipping_fee": "float", # 运费 "delivery_time": "string", # 配送时间 "return_policy": "string", # 退换政策 "crawl_time": "datetime", # 爬取时间}
4. 反爬策略
4.1 风险等级
| 行为 |
风险 |
建议频率 |
| 访问列表页 |
低 |
1 请求/秒 |
| 访问详情页 |
中 |
1 请求/2 秒 |
| 访问评论页 |
中 |
1 请求/2 秒 |
| 批量爬取 |
高 |
需代理 IP |
4.2 反爬措施
# 1. User-Agent 轮换USER_AGENTS = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...", # ... 50+ 个 User-Agent]# 2. 代理 IP 池PROXY_PROVIDERS = [ "brightdata.com", "oxylabs.io", # 预算有限可用免费代理 (不推荐生产环境)]# 3. 请求频率控制DOWNLOAD_DELAY = 2 # 2 秒间隔CONCURRENT_REQUESTS = 8 # 并发 8 个# 4. Cookie 管理COOKIES_ENABLED = TrueCOOKIES_DEBUG = False# 5. 随机等待RANDOMIZE_DOWNLOAD_DELAY = True
4.3 异常处理
# 常见状态码处理STATUS_CODE_HANDLING = { 200: "正常处理", 301: "跟随重定向", 302: "跟随重定向", 403: "被封禁,切换 IP", 404: "商品下架,记录", 429: "请求过多,等待重试", 500: "服务器错误,等待重试", 503: "服务不可用,等待重试",}# 重试机制RETRY_TIMES = 3RETRY_HTTP_CODES = [429, 500, 502, 503, 504]
5. 数据存储
5.1 数据库设计
-- 商品表CREATE TABLE products ( id SERIAL PRIMARY KEY, item_id VARCHAR(50) UNIQUE NOT NULL, title VARCHAR(500) NOT NULL, price DECIMAL(10,2), original_price DECIMAL(10,2), discount DECIMAL(5,2), currency VARCHAR(3) DEFAULT 'LKR', category_id VARCHAR(50), category_name VARCHAR(200), brand VARCHAR(200), seller_id VARCHAR(50), seller_name VARCHAR(200), rating DECIMAL(3,2), review_count INTEGER DEFAULT 0, sold_count INTEGER DEFAULT 0, stock_status VARCHAR(50), images JSONB, description TEXT, specifications JSONB, shipping_fee DECIMAL(10,2), delivery_time VARCHAR(100), return_policy TEXT, crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- 价格历史表 (用于价格趋势分析)CREATE TABLE price_history ( id SERIAL PRIMARY KEY, item_id VARCHAR(50) NOT NULL, price DECIMAL(10,2) NOT NULL, original_price DECIMAL(10,2), discount DECIMAL(5,2), crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (item_id) REFERENCES products(item_id));-- 销量历史表 (用于销量趋势分析)CREATE TABLE sales_history ( id SERIAL PRIMARY KEY, item_id VARCHAR(50) NOT NULL, sold_count INTEGER NOT NULL, crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (item_id) REFERENCES products(item_id));-- 评论表CREATE TABLE reviews ( id SERIAL PRIMARY KEY, item_id VARCHAR(50) NOT NULL, review_id VARCHAR(50) UNIQUE, user_name VARCHAR(200), rating INTEGER CHECK (rating >= 1 AND rating <= 5), comment TEXT, images JSONB, helpful_count INTEGER DEFAULT 0, crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (item_id) REFERENCES products(item_id));-- 创建索引CREATE INDEX idx_products_category ON products(category_id);CREATE INDEX idx_products_seller ON products(seller_id);CREATE INDEX idx_products_price ON products(price);CREATE INDEX idx_products_rating ON products(rating);CREATE INDEX idx_products_sold ON products(sold_count);CREATE INDEX idx_price_history_time ON price_history(crawl_time);CREATE INDEX idx_sales_history_time ON sales_history(crawl_time);
5.2 数据导出
# 导出为 AI 训练格式def export_for_training(): """ 导出为 JSONL 格式,用于 AI 模型训练 """ query = """ SELECT p.item_id, p.title, p.category_name, p.price, p.sold_count, p.rating, p.review_count, s.avg_price as avg_category_price, s.avg_sales as avg_category_sales, s.competition_score FROM products p LEFT JOIN ( SELECT category_id, AVG(price) as avg_price, AVG(sold_count) as avg_sales, COUNT(DISTINCT seller_id) / COUNT(DISTINCT item_id) as competition_score FROM products GROUP BY category_id ) s ON p.category_id = s.category_id WHERE p.crawl_time > NOW() - INTERVAL '30 days' """ # 导出为 JSONL # 每条记录包含:商品特征 + 类目平均水平 + 竞争度
6. 部署方案
6.1 爬虫架构
┌─────────────────────────────────────────────────────────┐│ 调度层 (Airflow) ││ - 定时任务调度 ││ - 任务依赖管理 ││ - 失败重试 │└─────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────┐│ 爬虫层 (Scrapy) ││ - 类目爬虫 (CategorySpider) ││ - 商品爬虫 (ProductSpider) ││ - 评论爬虫 (ReviewSpider) │└─────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────┐│ 存储层 (PostgreSQL) ││ - 商品数据 ││ - 价格历史 ││ - 销量历史 ││ - 评论数据 │└─────────────────────────────────────────────────────────┘
6.2 Docker 部署
# DockerfileFROM python:3.11-slimWORKDIR /app# 安装依赖COPY requirements.txt .RUN pip install -r requirements.txt# 复制代码COPY . .# 设置环境变量ENV PYTHONUNBUFFERED=1ENV SCRAPY_SETTINGS_MODULE=daraz_spider.settings# 运行爬虫CMD ["scrapy", "crawl", "product_spider"]
# docker-compose.ymlversion: '3.8'services: postgres: image: postgres:15 environment: POSTGRES_DB: daraz POSTGRES_USER: daraz_user POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" spider: build: . environment: DATABASE_URL: postgresql://daraz_user:${DB_PASSWORD}@postgres:5432/daraz PROXY_API_KEY: ${PROXY_API_KEY} depends_on: - postgres deploy: replicas: 3 # 3 个爬虫实例 airflow: image: apache/airflow:2.7.0 environment: - AIRFLOW__CORE__EXECUTOR=LocalExecutor volumes: - ./airflow/dags:/opt/airflow/dags ports: - "8080:8080" depends_on: - postgresvolumes: postgres_data:
7. 监控与告警
7.1 监控指标
| 指标 |
阈值 |
告警方式 |
| 爬取成功率 |
<90% |
Slack 通知 |
| 请求失败率 |
10%
|
Slack 通知 |
| IP 被封率 |
5%
|
邮件 + Slack |
| 数据量异常 |
< 预期 50% |
Slack 通知 |
| 数据库连接 |
失败 |
邮件 + Slack |
7.2 日志记录
# 日志配置LOGGING = { 'version': 1, 'handlers': { 'file': { 'class': 'logging.FileHandler', 'filename': 'logs/spider.log', }, 'slack': { 'class': 'slack_handler.SlackHandler', 'webhook_url': '${SLACK_WEBHOOK}', 'level': 'ERROR', }, }, 'loggers': { 'daraz_spider': { 'handlers': ['file', 'slack'], 'level': 'INFO', }, },}
8. 合规与道德
8.1 遵守规则
- ✅ 遵守 robots.txt
- ✅ 控制爬取频率,不影响正常用户
- ✅ 仅用于内部分析,不商用数据
- ✅ 不爬取用户隐私数据
8.2 数据使用
- ✅ 内部选品分析
- ✅ AI 模型训练
- ❌ 不出售数据
- ❌ 不公开数据集
9. 预算估算
| 项目 |
配置 |
价格 |
| 代理 IP |
Bright Data, 10GB/月 |
300/月 |
| 数据库 |
PostgreSQL (自建) |
0 |
| 合计 |
- |
~$800/月 |
预算有限方案:
- 使用免费代理 (稳定性差)
- 降低爬取频率
- 减少并发数
- 预算可降至 ~$200/月
10. 快速启动
10.1 环境准备
# 1. 克隆代码git clone [repo_url]cd daraz-spider# 2. 创建虚拟环境python -m venv venvsource venv/bin/activate # Linux/Mac# orvenv\Scripts\activate # Windows# 3. 安装依赖pip install -r requirements.txt# 4. 配置环境变量cp .env.example .env# 编辑 .env 文件,填写数据库、代理等配置# 5. 启动数据库docker-compose up -d postgres# 6. 运行爬虫scrapy crawl product_spider
10.2 测试爬取
# 测试爬取 10 个商品scrapy crawl product_spider -a limit=10# 测试爬取单个类目scrapy crawl category_spider -a category_id=10000312 -a max_pages=5# 导出测试数据scrapy crawl product_spider -o test_output.jsonl
版本: 1.0
创建时间: 2026-03-19
维护者: 技术团队