先说结果:折腾了一周,目前稳定每天采集Ozon约2万条商品数据,没有被ban过。
但过程挺曲折的。写出来,供遇到类似问题的同行参考。
一、项目背景
4月初,俄罗斯烧烤季的苗头出来了。Wildberries上电烤炉搜索量涨了38%,Ozon的烧烤配件也在涨。
老板让我搭建一套竞品监控系统,核心需求:
- 每天采集Ozon烧烤品类TOP500商品的价格、库存、评分
- 数据延迟不超过4小时
- 稳定运行,不能断
我当时觉得这事不难。结果第一天就翻车了。
二、第一版方案:requests + 免费代理
初始方案很简单:
import requests
proxies = {
'http': 'http://free-proxy:port',
'https': 'http://free-proxy:port'
}
response = requests.get('https://www.ozon.ru', proxies=proxies)
结果:
- 采集到第47条请求,返回403
- 换代理,跑了83条,又403
- 再换,发请求就直接超时
问题分析: 免费代理来源基本都是公开的代理池,IP段早就被Ozon拉黑了。连上就403,根本没法用。
三、第二版方案:数据中心代理 + 随机UA
痛定思痛,花钱买了某服务商的数据中心代理套餐,配了随机User-Agent轮换:
from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}
proxies = {...} # 数据中心代理
这次好一些。跑了大概300条请求才开始出现429。
但新的问题出现了:
- 采集到的价格,和网页上看到的不一样
- 有些商品信息直接是空的
- 同一个商品,不同时间采,数据差异很大
排查发现,Ozon会根据IP属地返回不同的商品页面。我用的是美国数据中心IP,看到的不是俄罗斯本地用户看到的真实价格和库存。
问题分析: 数据中心IP虽然便宜,但有两个致命问题:
- IP段特征明显,容易被风控识别
- 无法获取真实的本地化数据
四、第三版方案:住宅代理 + 俄罗斯节点
了解到问题出在IP上,我开始找带俄罗斯节点的住宅代理服务商。
最后选了辣椒HTTP,原因:
- 明确标注覆盖俄罗斯节点
- 可以按流量计费(5元/GB),小成本试错
- 支持SOCKS5协议
- 新用户有免费试用
拿到配置后开始测试:
proxies = {
'http': 'socks5://user:pass@proxy.lajiaohttp.com:port',
'https': 'socks5://user:pass@proxy.lajiaohttp.com:port'
}
response = requests.get(
'https://www.ozon.ru/product/123456',
proxies=proxies,
timeout=15
)
第一轮测试跑了500条请求,全部成功,没有403,没有429。
关键是用俄罗斯住宅IP访问,返回的商品价格、促销信息、库存状态,和本地用户看到的一致。
五、细节优化:行为模拟
IP问题解决了,但还是怕跑太久被风控。做了几层优化:
1. 请求间隔随机化
不要固定间隔,模拟人类操作节奏:
import random
import time
interval = random.uniform(3, 8) # 3-8秒随机间隔
time.sleep(interval)
2. 补充完整请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'ru-RU,ru;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Referer': 'https://www.ozon.ru/'
}
3. 会话粘性设置
辣椒HTTP支持会话粘性,可以在采集一个商品的多个页面时保持同一IP:
# 设置session_id保持会话
session_id = "ozon_bbq_collector_01"
proxies = f"socks5://{session_id}:{password}@proxy.lajiaohttp.com:port"
4. 异常重试
def fetch_with_retry(url, max_retries=3):
for i in range(max_retries):
try:
resp = requests.get(url, headers=headers, proxies=proxies, timeout=10)
if resp.status_code == 200:
return resp.text
except Exception as e:
print(f"第{i+1}次失败: {e}")
time.sleep(5)
return None
六、成本核算
目前每日采集约2万条商品数据的流量消耗:
| 项目 | 数据量 |
|---|
| 日请求量 | ~2万次 |
| 平均响应大小 | ~50KB |
| 日流量 | ~1GB |
| 月流量 | ~30GB |
| 月成本(5元/GB) | 约150元 |
如果加上静态IP管理店铺账号,9.9元/个/月,性价比确实可以。
七、踩坑总结
回头看,核心卡点其实是两个:
- IP类型选错了:数据中心IP不适合做Ozon这类严格平台的采集
- 地域没匹配:用非俄罗斯IP,采到的数据是“假的”
换成俄罗斯住宅IP后,两个问题同时解决了。
一些经验:
- 先试IP质量再写代码:别花一周写完采集脚本,发现IP全被ban了
- 找支持试用的服务商:辣椒HTTP有免费流量,测俄罗斯节点稳定不稳定再决定
- 控制节奏比换IP更重要:住宅IP也不能狂刷,随机延迟必须加
- 本地化数据才是有效数据:采A地区的数据,必须用A地区的IP
八、最终方案架构
┌─────────────────────────────────────────┐
│ 采集任务调度器 │
│ 每天定时触发,按品类分批采集 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 辣椒HTTP代理池 │
│ • 俄罗斯住宅IP(莫斯科/圣彼得堡) │
│ • SOCKS5协议,会话粘性 │
│ • 自动轮换 + 随机延迟 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Ozon数据采集 │
│ • 价格 | 库存 | 评分 | 销量排名 │
│ • 3-8秒随机间隔 │
│ • 异常自动重试 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 数据存储与告警 │
│ • 存入MySQL,每日差异对比 │
│ • 价格波动>10%自动推送 │
└─────────────────────────────────────────┘
这套方案跑了将近两周,目前稳定。不过每个站点的风控策略不一样,仅供参考。
九、写在最后
做采集这一年,最大的感受是:
IP质量决定数据质量。
尤其做俄罗斯这类独立市场的卖家,本地化数据是选品和定价的基础。用非本土IP采到的数据,轻则决策偏差,重则库存积压。
如果你也在做Ozon或Wildberries的数据采集,建议优先解决两个问题:
- 找带俄罗斯住宅IP的服务商(辣椒HTTP可以一试)
- 控制好请求节奏,别贪快
有具体问题欢迎交流。技术问题我知道的都会说,商业敏感的就无可奉告了。
以上配置基于实测环境,不同站点策略不同,请根据实际情况调整。辣椒HTTP相关信息来自官网公开资料。