技术方向:反爬虫对抗 / 动态数据采集
关键词:雅虎代拍、日本雅虎、Bidfins、日本代购、北极星日淘
一、业务场景与技术挑战
最近在做一个跨境电商数据监控项目,需要实时采集日本雅虎拍卖(auctions.yahoo.co.jp)的商品信息——包括当前出价、剩余时间、竞拍人数等关键字段。这类数据对价格监控和竞拍策略分析至关重要,但雅虎的反爬机制相当严格。
实际测试中发现,直接用requests库发送请求,返回的HTML里根本没有商品价格数据——页面通过JavaScript动态渲染,基础爬虫只能拿到空值。更麻烦的是,短时间内多次请求会触发IP封禁,返回403错误。
本文分享一套完整的解决方案:Playwright模拟登录 + 接口抓包解析 + 代理IP轮换,实现雅虎拍卖商品的稳定数据采集。
二、技术选型与架构设计
text
┌─────────────────────────────────────────────────────────┐│ 数据采集架构 │├─────────────────────────────────────────────────────────┤│ 调度层 → Celery Beat 定时触发(每30秒) ││ 采集层 → Playwright + asyncio 异步并发 ││ 解析层 → 抓包分析API接口,直接解析JSON ││ 存储层 → MongoDB(商品数据)+ Redis(去重缓存) ││ 代理层 → 住宅代理池动态轮换 │└─────────────────────────────────────────────────────────┘
选用Playwright而非Selenium,主要因为它无需手动配置浏览器驱动,且对动态渲染页面的支持更稳定。
三、核心代码实现
3.1 模拟登录与获取登录态
python
from playwright.sync_api import sync_playwrightimport jsondef yahoo_login(username: str, password: str): """模拟登录日本雅虎,返回登录后的上下文""" with sync_playwright() as p: browser = p.chromium.launch(headless=False) context = browser.new_context( user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" ) page = context.new_page() # 访问雅虎登录页 page.goto("https://login.yahoo.co.jp/") page.fill('input[name="login"]', username) page.fill('input[name="passwd"]', password) page.click('button[type="submit"]') # 等待登录完成 page.wait_for_load_state("networkidle") # 保存cookies供后续请求使用 cookies = context.cookies() with open("yahoo_cookies.json", "w") as f: json.dump(cookies, f) return context
3.2 抓包分析获取真实数据接口
打开雅虎拍卖商品页,按F12进入开发者工具 → Network → XHR,刷新页面后找到返回商品数据的接口。雅虎的数据接口通常是https://auctions.yahoo.co.jp/api/xxx格式,返回JSON数据。
python
import requestsimport randomimport timedef fetch_auction_data(item_id: str, cookies: dict): """通过API接口获取商品实时数据""" url = f"https://auctions.yahoo.co.jp/api/v1/items/{item_id}" # 代理池动态轮换 proxies = get_proxy() headers = { "User-Agent": random.choice(UA_POOL), "Referer": f"https://auctions.yahoo.co.jp/item/{item_id}", "Accept": "application/json", "Cookie": format_cookies(cookies) } try: resp = requests.get(url, headers=headers, proxies=proxies, timeout=10) if resp.status_code == 200: data = resp.json() return { "current_price": data.get("current_price"), "end_time": data.get("end_time"), "bid_count": data.get("bid_count"), "status": data.get("status") } elif resp.status_code == 403: # IP被封,切换代理重试 refresh_proxy() return fetch_auction_data(item_id, cookies) except Exception as e: print(f"请求失败: {e}") return None
3.3 代理池管理与请求控制
python
import redisfrom typing import Listclass ProxyManager: """代理池管理器""" def init(self): self.redis_client = redis.Redis(host='localhost', port=6379, db=0) self.proxy_key = "proxy_pool" def get_proxy(self) -> dict: """从池中随机获取一个代理""" proxies = self.redis_client.smembers(self.proxy_key) if not proxies: return None proxy = random.choice(list(proxies)).decode() return {"http": proxy, "https": proxy} def mark_invalid(self, proxy: str): """标记失效代理""" self.redis_client.srem(self.proxy_key, proxy) # 请求间隔控制 - 模拟人类浏览节奏[reference:4] def random_delay(self): time.sleep(random.uniform(1.5, 3.5))
四、踩坑与解决方案
坑1:无头模式被检测
使用Playwright的无头模式(headless=True)访问雅虎时,会触发验证机制。解决方案:使用有头模式或添加--disable-blink-features=AutomationControlled参数。
坑2:Cookie过期
雅虎的登录Cookie有效期约24小时。解决方案:使用schedule库定时刷新登录态。
坑3:请求频率控制
单IP每10秒超过5次请求即触发封禁。解决方案:控制单IP请求间隔1-3秒,配合代理池轮换。
五、总结
这套方案已稳定运行3个月,日均采集商品数据超过10万条。核心经验:抓包分析接口比解析HTML更高效,代理池配合请求间隔控制比单纯堆IP更有效。
类似的架构同样适用于煤炉(Mercari)、乐天等日本电商平台的数据采集。如果你也在做日本跨境电商的数据监控,这套方案可以直接复用。