a9d2edc9654d5235645641990184226f1b3f6e43
日本跨境电商采购自动化下单工具 (首期:骏河屋)
本项目是一个为日本电商网站(首期重点支持:骏河屋 Surugaya)设计的生产级、高稳定性、长期可持续运行的浏览器自动化采购下单系统。
🪐 技术架构与设计亮点
- 核心驱动:基于 Python 3.12+ (Asyncio) + Playwright (Async API)。全部使用异步协同技术,资源消耗低、性能极高。
- 多账号串行锁隔离:
- 内存中维护针对
account_id维度的asyncio.Lock协程锁。 - 实现同一个账号串行执行(规避多开浏览器登录冲突/风控),不同账号并发运行。
- 内存中维护针对
- 隔离数据环境 (Session 隔离):
- 每个账号在配置中独占一个
user_data_dir浏览器环境。 - 自动持久化 Cookie、购物车和登录状态,无须每次做短信验证码登录。
- 每个账号在配置中独占一个
- 强特征隐藏防爬:
- 抹除网页端的
navigator.webdriver痕迹。 - 注入防指纹脚本(WebGL供应商混淆、多语言偏好
ja-JP、标准 Chrome 插件列表伪装)。 - 配合首选日语区域、东京时区,深度规避 Cloudflare, Akamai 等反爬检测。
- 抹除网页端的
- 结构化非阻塞日志 (Loguru):
- 支持设置
DEBUG、INFO、ERROR日志级别。 - 日志在独立的日志缓冲队列中异步写入,绝不拖慢自动化线程。
- 每天
00:00自动切割日志文件,默认最多保留 14 天并压缩打包成 zip。
- 支持设置
- 故障截图与自动归档:
- 在采购关键节点(如购买前确认)及发生任何执行崩溃时,系统自动捕获紧急截图。
- 自动按照日期、Topic 智能规划保存目录:
archives/YYYYMMDD/{topic}/{scene}_{timestamp}.png
- 任务级桌面录屏 (FFmpeg,可选):
- 录屏开关通过采购消息中的
record_video字段控制,默认关闭。 - 开启后使用 FFmpeg 录制整个桌面,可覆盖浏览器窗口、系统弹层和鼠标操作过程。
- 任务结束后自动归档视频到:
archives/YYYYMMDD/{topic}/video_{task_id}_{timestamp}.mp4
- 录屏开关通过采购消息中的
📂 项目目录结构
jp_purchase_zdh_5/
├── .env.dev # 本地开发环境环境变量
├── .env.prod # 生产部署环境环境变量
├── pyproject.toml # 现代依赖管理配置文件 (PEP 621)
├── accounts.yaml # 站点多账号隔离配置文件
├── README.md # 项目运行配置手册
├── logs/ # 自动生成的日志切片目录 (Git已忽略)
├── archives/ # 自动截图及归档素材目录 (Git已忽略)
└── src/ # 核心源代码
├── __init__.py
├── main.py # 进程启动入口 (主信号拦截、服务初始化)
├── config/
│ ├── __init__.py
│ ├── settings.py # Pydantic Settings 全局配置管理
│ └── accounts.py # Pydantic 账号解析器 (YAML 结构化解析)
├── queue/
│ ├── __init__.py
│ ├── listener.py # Redis Stream 持续监听器 (PEL 奔溃恢复、优雅停机)
│ └── dispatcher.py # 采购任务分发器 (基于账号协程锁并发串行控制)
├── browser/
│ ├── __init__.py
│ └── manager.py # Playwright 浏览器实例管理 (数据隔离、隐藏测试特征)
├── tasks/
│ ├── notifications/
│ │ ├── __init__.py
│ │ ├── service.py # 通知服务入口 (事件路由、配置校验、渠道分发)
│ │ └── channels/
│ │ └── email.py # SMTP 邮件通知渠道
│ ├── __init__.py
│ ├── base.py # 任务基类 (Playwright 生命周期、通用异常捕获、截图归档)
│ └── surugaya.py # 骏河屋 (Surugaya) 采购业务骨架实现
└── utils/
└── utils/
├── __init__.py
└── logger.py # Loguru 结构化分割日志配置
🛠 快速上手指南
1. 安装项目依赖
本项目推荐使用 uv 进行极速的依赖和环境管理。确保您的操作系统上已安装 uv(且 Python 版本 >= 3.12):
# 使用 uv 同步并安装所有依赖(自动创建并管理 .venv 虚拟环境)
uv sync
# 安装 Playwright 核心驱动浏览器
uv run playwright install chromium
传统模式(不使用 uv): 如果您没有安装
uv,也可以使用传统的pip方式进行安装:# 1. 激活您的虚拟环境 (venv) python -m venv .venv source .venv/bin/activate # Windows 下使用: .venv\Scripts\activate # 2. 安装项目核心库 (建议使用 pip) pip install -e . # 3. 安装 Playwright 核心驱动浏览器 playwright install chromium
2. 账号的配置、新增与调整
系统所有的可用账号均在根目录的 accounts.yaml 中定义:
- 新增账号:在
surugaya节点下增加- account_id: "surugaya_acc_0X",并给出一个独立的user_data_dir缓存路径(如./user_data/surugaya/acc_0X)。重启程序即可被正常识别。 - 调整密码/用户名:直接编辑对应的参数。
- 重置登录状态 (清除 Cookie 重新登录):无需更改任何代码,直接在物理硬盘上删除该账号对应的缓存文件夹(例如
./user_data/surugaya/acc_01),再次运行任务时 Playwright 会为您初始化全新的纯净浏览器环境。
3. 通知模块配置
通知模块与采购业务解耦,作为独立基础设施存在。第一期仅支持邮件通知,并且默认只在采购任务失败时触发。
在 .env.dev 或 .env.prod 中新增以下配置:
NOTIFY_ENABLED=true
NOTIFY_CHANNELS=email
NOTIFY_ON_TASK_FAILED=true
MAIL_ENABLED=true
MAIL_SMTP_HOST=smtp.example.com
MAIL_SMTP_PORT=465
MAIL_SMTP_USE_SSL=true
MAIL_SMTP_STARTTLS=false
MAIL_USERNAME=bot@example.com
MAIL_PASSWORD=your-password
MAIL_FROM_ADDRESS=bot@example.com
MAIL_FROM_NAME=JP Purchase Bot
MAIL_TO_ADDRESSES=ops@example.com,owner@example.com
MAIL_SUBJECT_PREFIX=[JP-Purchase]
MAIL_TIMEOUT_SECONDS=10
说明:
NOTIFY_ENABLED是通知总开关。NOTIFY_CHANNELS预留多渠道扩展能力,第一期请填写email。MAIL_TO_ADDRESSES支持多个收件人,使用英文逗号分隔。- 若邮件配置不完整,程序会打印告警日志,但不会阻止主进程启动,也不会影响任务 ACK。
⚡ 运行采购守护进程
通过 APP_ENV 环境变量区分本地开发与生产配置。
开发环境下启动 (加载 .env.dev):
# Windows Power Shell (使用 uv 推荐)
$env:APP_ENV="dev"; uv run python -m src.main
# Linux / macOS CMD (使用 uv 推荐)
APP_ENV=dev uv run python -m src.main
# --- 传统模式 (不使用 uv,需确保已激活虚拟环境) ---
# Windows Power Shell
# $env:APP_ENV="dev"
# python -m src.main
#
# Linux / macOS CMD
# APP_ENV=dev python -m src.main
生产环境下启动 (加载 .env.prod):
# Windows Power Shell (使用 uv 推荐)
$env:APP_ENV="prod"; uv run python -m src.main
# Linux / macOS CMD (使用 uv 推荐)
APP_ENV=prod uv run python -m src.main
# --- 传统模式 (不使用 uv,需确保已激活虚拟环境) ---
# Windows Power Shell
# $env:APP_ENV="prod"
# python -m src.main
#
# Linux / macOS CMD
# APP_ENV=prod python -m src.main
🧪 模拟测试指南
Redis Stream 采购任务的消息结构体设计如下,你可以通过 Redis CLI 向 Stream 发送任务消息:
- 推荐将
record_video放在消息顶层;系统也兼容payload.record_video。 - 开启录屏前请确保运行环境已安装并可直接调用
ffmpeg。
# 向 Stream (purchase:tasks) 中投递一个骏河屋采购任务,并开启整桌面录屏
XADD purchase:tasks * task_id "task_test_1001" topic "surugaya_tasks" purchase_account "surugaya_acc_01" site_id "surugaya" record_video "1" payload "{\"item_list\":[{\"id\":\"m72275988725\",\"price_limit\":6500,\"number\":1}]}"
服务启动后,系统会:
- 监听到上述消息并将其解析。
- 调度
surugaya_tasks的任务处理器SurugayaPurchaseTask。 - 获取该账号
surugaya_acc_01的协程串行锁,隔离并发启动 Playwright 缓存环境。 - 打开目标商品,到达确认环节截图并按目录保存:
archives/YYYYMMDD/surugaya_tasks/购买前确认_{timestamp}.png。 - 若
record_video="1",任务结束后会输出视频文件名与绝对路径,并归档到:archives/YYYYMMDD/surugaya_tasks/video_task_test_1001_{timestamp}.mp4。 - 任务结束后自动进行
XACK确认并安全关舱。 - 若任务执行失败且通知模块已启用,系统会向
MAIL_TO_ADDRESSES中配置的收件人发送失败邮件,邮件正文包含任务 ID、账号、错误原因、截图路径和录屏路径。
Description
Languages
Python
98.1%
Dockerfile
1.5%
Shell
0.4%