探针实测发现 httpx 因 TLS/HTTP2 指纹被 Rakuten 拒认(cookie 有效但 站点不识别 session),site_interact 改为全程 Playwright + storage_state。 add_to_cart 与 verify_cart 已实测可用:从商品页 __INITIAL_STATE__ 抽 purchase 块、调用方补 variant_id 与 choice、POST basketDomain、用 cart count JSONP API 与 SPA 渲染后的 cart 页校验。enter_checkout 及之后仍 NotImplementedError:Rakuten 对 checkout 要求 session upgrade(重输密码), 是自动 checkout 的硬墙,未实测过墙方案前留接口缝。 SiteInteractor 类持有 Playwright BrowserContext,由 WorkerRunner 实例 持有、container/main 接线、lifespan 管理生命周期。测试侧 23 个用例, 全套件 333 passed,架构边界守住。 附 5 个探针脚本(scripts/probe_*.py),记录实测路径与响应结构。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
39 lines
1.8 KiB
Python
39 lines
1.8 KiB
Python
"""交易服务容器:集中管理交易侧服务实例,用于依赖注入
|
|
|
|
持有两类东西:
|
|
- 登录态会话(auth_session)——加购与下单必须用同一份 cookie,全程共享
|
|
- 本地下单 worker(可选)——RAKUTEN_ORDER_GATEWAY_URL 留空时整套不构造
|
|
|
|
worker 的子组件(gateway_client / local_db / evidence_store / runner)都在
|
|
app.trading.worker 包内,与抓取/网关互不 import;worker 需要商品数据时走抓取
|
|
服务的 HTTP 接口,需要任务调度时走网关的 HTTP 接口。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from app.shared.config import Settings
|
|
from app.trading.services.auth_session import AuthSession
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class TradingContainer:
|
|
"""交易服务容器
|
|
|
|
与抓取容器最本质的差别不是字段多少,而是**这个进程有状态**:登录态、
|
|
订单、页面证据都属于某个具体账号,因此交易服务只能单实例运行
|
|
(或按账号分片),不能像抓取服务那样随意横向扩容。
|
|
|
|
worker_* 字段在 RAKUTEN_ORDER_GATEWAY_URL 留空时为 None——此时交易服务
|
|
只跑登录态接口,不起后台 worker。
|
|
"""
|
|
|
|
settings: Settings
|
|
auth_session: AuthSession
|
|
# 以下五项仅在 order_gateway_url 配置时构造;否则为 None,worker 不启动
|
|
worker_client: object | None = None # app.trading.worker.client.GatewayClient
|
|
worker_local_db: object | None = None # app.trading.worker.local_db.LocalDB
|
|
worker_evidence: object | None = None # app.trading.worker.evidence.EvidenceStore
|
|
worker_site: object | None = None # app.trading.worker.site_interact.SiteInteractor
|
|
worker_runner: object | None = None # app.trading.worker.runner.WorkerRunner
|