爬虫项目实战:抓取电商数据

完整项目,从分析到代码实现

一、项目背景

电商数据采集是爬虫最常见的应用场景之一。无论是价格监控、竞品分析还是市场研究,都需要从电商平台获取商品信息。

这篇文章以一个简化的电商数据采集项目为例,完整展示从需求分析到代码实现的整个过程。

项目目标
  • 采集商品列表页数据
  • 提取商品名称、价格、销量等信息
  • 处理分页和反爬
  • 数据保存到 JSON 文件

二、需求分析

2.1 数据来源

以某电商平台的商品列表页为例,URL 格式为:

https://api.example.com/items?keyword=手机&page=1&size=20

2.2 数据结构

{ "code": 0, "data": { "items": [ { "id": "12345", "title": "iPhone 15 Pro", "price": 7999.00, "sales": 10000, "shop": "Apple 官方旗舰店" } ], "total": 1000 } }

三、环境准备

# 安装依赖 pip install requests pip install fake-useragent

四、代码实现

4.1 基础爬虫

import requests import json import time import random from fake_useragent import UserAgent class EcommerceCrawler: def __init__(self): self.ua = UserAgent() self.session = requests.Session() self.base_url = 'https://api.example.com/items' def get_headers(self): return { 'User-Agent': self.ua.random, 'Accept': 'application/json', 'Referer': 'https://www.example.com' } def fetch_page(self, keyword, page=1, size=20): """获取一页数据""" params = { 'keyword': keyword, 'page': page, 'size': size } try: response = self.session.get( self.base_url, params=params, headers=self.get_headers(), timeout=10 ) response.raise_for_status() return response.json() except Exception as e: print(f"请求失败: {e}") return None def parse_items(self, data): """解析商品数据""" if not data or data.get('code') != 0: return [] items = data['data']['items'] results = [] for item in items: results.append({ 'id': item.get('id'), 'title': item.get('title'), 'price': item.get('price'), 'sales': item.get('sales'), 'shop': item.get('shop') }) return results def crawl(self, keyword, max_pages=5): """采集数据""" all_items = [] for page in range(1, max_pages + 1): print(f"正在采集第 {page} 页...") data = self.fetch_page(keyword, page) if not data: break items = self.parse_items(data) all_items.extend(items) print(f"第 {page} 页采集完成,获取 {len(items)} 条数据") # 随机延时 time.sleep(random.uniform(1, 3)) return all_items def save(self, data, filename='items.json'): """保存数据""" with open(filename, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"数据已保存到 {filename}") # 使用 crawler = EcommerceCrawler() items = crawler.crawl('手机', max_pages=3) crawler.save(items)

4.2 添加代理

class EcommerceCrawler: def __init__(self): # ... 其他初始化 ... self.proxies = [ 'http://proxy1.example.com:8080', 'http://proxy2.example.com:8080', ] def get_proxy(self): return {'http': random.choice(self.proxies)} def fetch_page(self, keyword, page=1, size=20): # ... 添加代理 ... response = self.session.get( self.base_url, params=params, headers=self.get_headers(), proxies=self.get_proxy(), timeout=10 )

五、运行与测试

# 运行爬虫 python crawler.py # 输出: # 正在采集第 1 页... # 第 1 页采集完成,获取 20 条数据 # 正在采集第 2 页... # 第 2 页采集完成,获取 20 条数据 # 正在采集第 3 页... # 第 3 页采集完成,获取 20 条数据 # 数据已保存到 items.json

六、优化与扩展

6.1 添加重试机制

from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry class EcommerceCrawler: def __init__(self): self.session = requests.Session() # 配置重试 retries = Retry( total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504] ) self.session.mount('http://', HTTPAdapter(max_retries=retries)) self.session.mount('https://', HTTPAdapter(max_retries=retries))

6.2 多线程采集

from concurrent.futures import ThreadPoolExecutor class EcommerceCrawler: def crawl_multi_thread(self, keyword, max_pages=5, workers=3): """多线程采集""" all_items = [] with ThreadPoolExecutor(max_workers=workers) as executor: futures = [ executor.submit(self.fetch_page, keyword, page) for page in range(1, max_pages + 1) ] for future in futures: data = future.result() if data: items = self.parse_items(data) all_items.extend(items) return all_items

七、总结

这个电商爬虫项目展示了爬虫开发的基本流程:

  1. 分析接口和数据结构
  2. 编写基础请求代码
  3. 添加反爬处理
  4. 优化性能和稳定性