Files
pruchase_jhw/docs/DEPLOYMENT_WINDOWS.md
T
2026-06-25 13:59:58 +08:00

16 KiB

Windows 裸机部署指南

本文档说明如何在 Windows 裸机环境下部署以下两个互相配合的服务,不依赖 Docker 或 WSL。 部署对象:

  • jp_pruchase_zdh_5:采购自动化 worker(浏览器自动化下单、定时抓取通知/订单、截图归档)。
  • ../jp_surugaya:骏河屋抓取 API 服务(搜索/详情/通知/订单查询,并可向 Redis 投递采购任务)。

两个服务通过 Redis 共享任务队列与状态数据;Redis 由 ../jp_surugaya 侧统一部署,本服务(采购 worker)只需配置连接信息。


1. 部署架构

┌─────────────────────────────────────────────────────────────┐
│                        Windows 服务器                        │
│  ┌──────────────────┐         ┌──────────────────────────┐  │
│  │   jp_surugaya    │◄───────►│     Redis (Windows)      │  │
│  │   :31106         │         │     :6379                │  │
│  └──────────────────┘         └───────────┬──────────────┘  │
│           ▲                               │                 │
│           │ HTTP API                      │ Redis Stream    │
│           ▼                               ▼                 │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              jp_pruchase_zdh_5                       │  │
│  │  - 消费采购任务                                       │  │
│  │  - 浏览器自动化(Playwright)                          │  │
│  │  - 截图/录屏归档到 archives/                          │  │
│  │  - 截图查看 API :8080                                 │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
  • Redis:由 ../jp_surugaya 侧统一部署和维护,采购 worker 通过其连接信息接入。
  • jp_surugaya:对外提供 HTTP API(默认 0.0.0.0:31106),内部通过 Redis 读写任务与抓取结果。
  • jp_pruchase_zdh_5:不直接对外暴露业务端口,但内置截图查看 API(默认 0.0.0.0:8080),建议仅本地或内网访问。

2. 环境准备

2.1 操作系统

  • Windows 10/11 64 位,或 Windows Server 2019/2022。
  • 建议固定显示分辨率(例如 1920x1080),并保证登录会话处于交互式桌面环境(本地显示器或持续 RDP 会话)。

2.2 Python

  • 安装 Python 3.12+(推荐从 python.org 下载)。
  • 安装时勾选 Add python.exe to PATH
  • 验证:
python --version

2.3 uv(推荐)

两个项目均使用 uv 作为包管理器。安装方式:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

安装完成后重启 PowerShell,并验证:

uv --version

2.4 Redis 接入信息

Redis 由 ../jp_surugaya 侧统一部署,本服务不需要单独安装 Redis。

部署采购 worker 前,只需确认以下信息:

  • Redis 主机地址、端口、密码、DB 编号。
  • 采购 worker 与 ../jp_surugaya 必须访问同一个 Redis 实例。

若本地开发测试时需要临时 Redis,可另行准备 Windows 版 Redis 或 Memurai;生产环境建议统一使用 ../jp_surugaya 提供的实例。

2.5 浏览器

两个项目都基于 Playwright。首次部署时安装 Chromium:

uv run playwright install chromium

默认使用 Playwright 自带的 Chromium。若 accounts.yaml / .env 中指定了 browser_channel=chrome,请额外安装 Google Chrome 并确保其在系统 PATH 中可被找到。

2.6 FFmpeg(可选)

仅在需要开启任务级桌面录屏时安装:

  1. ffmpeg.org 下载 Windows build。
  2. 解压后将 bin 目录加入系统 PATH。
  3. 验证:
ffmpeg -version

3. 目录规划示例

建议将两个仓库放在同一父目录下,便于统一管理:

C:\jp-deploy\
├── jp_pruchase_zdh_5\      # 采购 worker
├── jp_surugaya\             # 抓取 API(含 Redis)
├── chrome-profile\          # 浏览器登录态持久化目录
│   ├── acc_01\
│   └── acc_02\
├── archives\                # 截图/录屏归档(可选,也可放在项目内)
└── logs\                    # 日志汇总(可选)

后续示例均基于以上目录。


4. 部署 jp_surugaya(抓取服务)

4.1 进入项目目录

cd C:\jp-deploy\jp_surugaya

4.2 配置环境变量

复制示例文件:

copy .env.example .env

编辑 .env,生产环境最小可用示例如下:

# 服务监听
SURUGAYA_APP_HOST=0.0.0.0
SURUGAYA_APP_PORT=31106
SURUGAYA_APP_ENV=prod

# 日志
SURUGAYA_LOG_LEVEL=INFO
SURUGAYA_LOG_TO_FILE=true
SURUGAYA_LOG_DIR=logs

# API 鉴权(必须替换为强随机字符串)
SURUGAYA_BEARER_TOKEN=REPLACE_WITH_STRONG_RANDOM_TOKEN

# 浏览器
SURUGAYA_BROWSER_ENABLED=true
SURUGAYA_BROWSER_HEADLESS=false
SURUGAYA_BROWSER_CHANNEL=
SURUGAYA_BROWSER_KEEP_OPEN_ON_ERROR=false

# 代理(建议日本 IP)
SURUGAYA_PROXY_SERVER=http://127.0.0.1:7890
SURUGAYA_PROXY_USERNAME=
SURUGAYA_PROXY_PASSWORD=

# Redis(与采购 worker 使用同一实例)
SURUGAYA_REDIS_HOST=127.0.0.1
SURUGAYA_REDIS_PORT=6379
SURUGAYA_REDIS_PASSWORD=
SURUGAYA_REDIS_DB=0

注意:

  • SURUGAYA_APP_ENV 要与采购 worker 的 APP_ENV 保持一致(推荐均为 prod),否则 Redis key 后缀不同,会导致通知/订单数据互相看不到。
  • 若不需要无头调试,Windows 裸机建议保持 SURUGAYA_BROWSER_HEADLESS=false,便于观察 Cloudflare 页面。

4.3 安装依赖与浏览器

# 如果私有 PyPI 索引需要认证,先设置用户名密码
$env:UV_INDEX_JERRYYAN_USERNAME="your_username"
$env:UV_INDEX_JERRYYAN_PASSWORD="your_password"

uv sync
uv run playwright install chromium

4.4 启动服务

项目已提供 PowerShell 启动脚本,推荐直接使用:

.\start-server.ps1

可选参数:

  • -Port 31106:指定端口。
  • -HostName 0.0.0.0:指定监听地址。
  • -NoKillExisting:端口占用时不自动结束旧进程。
  • -DryRun:仅做检查,不实际启动。

如果不希望使用脚本,也可以手动启动:

uv run python -m app.main

4.5 验证

curl http://127.0.0.1:31106/health

测试带鉴权的搜索接口:

curl -H "Authorization: Bearer REPLACE_WITH_STRONG_RANDOM_TOKEN" `
  -H "Content-Type: application/json" `
  -X POST "http://127.0.0.1:31106/api/search" `
  -d '{"search_word":"cat","category":"","page":1}'

5. 部署 jp_pruchase_zdh_5(采购 worker)

5.1 进入项目目录

cd C:\jp-deploy\jp_pruchase_zdh_5

5.2 配置环境变量

复制示例文件为生产配置:

copy .env.example .env.prod

编辑 .env.prod,生产环境最小可用示例如下:

APP_ENV=prod
LOG_LEVEL=INFO
LOG_DIR=./logs

# Redis(必须与 jp_surugaya 同一实例)
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0

# 消费者标识(多 worker 部署时建议为每个实例设置唯一名称)
REDIS_CONSUMER_GROUP=purchase_group
REDIS_CONSUMER_NAME=purchase_worker_01

# Redis key 名称(与 jp_surugaya 共用,prod 环境不带 _dev 后缀)
# 这些 key 的默认值已由 surugaya-common 的 redis_keys 定义一致,通常无需显式覆盖
REDIS_STREAM_KEY=jp_surugaya_purchase_task
REDIS_DELAY_ZSET_KEY=jp_surugaya_trade_delay
REDIS_NEWS_HASH_KEY=jp_surugaya_news
REDIS_TRADE_FETCH_STREAM_KEY=jp_surugaya_trade_fetch
REDIS_TRADE_FETCH_CONSUMER_GROUP=surugaya_trade_fetch_group
REDIS_TRADE_FETCH_CONSUMER_NAME=surugaya_trade_fetch_worker

# 节点标识(用于 trade delay zset,最终 key 为 REDIS_DELAY_ZSET_KEY:NODE_ID)
NODE_ID=node_1

# 通知定时抓取
NEWS_FETCH_ENABLED=true
NEWS_FETCH_INTERVAL_SECONDS=300

# 浏览器
BROWSER_HEADLESS=false
BROWSER_EXECUTABLE_PATH=
BROWSER_KEEP_OPEN=false
LOGIN_PRECHECK_ENABLED=true

# 配置与资源路径
ACCOUNTS_CONFIG_PATH=./accounts.yaml
SCREENSHOT_DIR=./archives

# 任务上报(按需配置回调地址与签名密钥)
CALLBACK_URL=
APPID=
APP_SECRET=

# 通知配置(失败时发邮件)
NOTIFY_ENABLED=false
NOTIFY_CHANNELS=email
NOTIFY_ON_TASK_FAILED=true

MAIL_ENABLED=true
MAIL_SMTP_HOST=
MAIL_SMTP_PORT=465
MAIL_SMTP_USE_SSL=true
MAIL_SMTP_STARTTLS=false
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME=JP Purchase Bot
MAIL_TO_ADDRESSES=ops@example.com
MAIL_SUBJECT_PREFIX=[JP-Purchase]
MAIL_TIMEOUT_SECONDS=10

注意:

  • Redis 实例由 ../jp_surugaya 侧统一部署,本配置只需填写正确的连接信息。
  • APP_ENV=prod 时,Stream / Hash / ZSet 的 key 默认不带 _dev 后缀;若 jp_surugaya 与采购 worker 的 prod/dev 环境不一致,会出现通知/订单数据互相看不到、任务投递后无法消费等问题。
  • REDIS_DELAY_ZSET_KEY 最终使用的 key 为 {REDIS_DELAY_ZSET_KEY}:{NODE_ID},因此 NODE_ID 必须与 jp_surugaya 调用 /api/order/add_trade_monitor 时传入的 node_id 保持一致。

5.3 配置账号

编辑项目根目录的 accounts.yaml。Windows 裸机部署示例:

sites:
  surugaya:
    - account_id: "acc_01"
      username: "your_username@example.com"
      password: "your_password"
      # 使用绝对路径,建议使用正斜杠
      user_data_dir: "C:/jp-deploy/chrome-profile/acc_01"
      proxy: "http://127.0.0.1:7890"

    - account_id: "acc_02"
      username: "your_username2@example.com"
      password: "your_password2"
      user_data_dir: "C:/jp-deploy/chrome-profile/acc_02"
      proxy: "http://127.0.0.1:7890"

  mercari: []
  yahoo: []

提示:

  • user_data_dir 用于持久化浏览器登录态;首次启动前确保目录已存在。
  • 如需清除登录态重新登录,直接删除对应目录即可。
  • 密码若为空字符串 "",系统会尝试使用已有 Cookie 登录。

5.4 安装依赖与浏览器

# 如果私有 PyPI 索引需要认证,先设置用户名密码
$env:UV_INDEX_JERRYYAN_USERNAME="your_username"
$env:UV_INDEX_JERRYYAN_PASSWORD="your_password"

uv sync
uv run playwright install chromium

5.5 启动 worker

$env:APP_ENV="prod"
uv run python -m src.main

启动后,worker 会:

  1. 加载 .env.prodaccounts.yaml
  2. 预热所有已配置账号的浏览器上下文。
  3. 执行登录预检(LOGIN_PRECHECK_ENABLED=true)。
  4. 启动 Redis Stream 监听器、延迟任务监听器、订单抓取监听器、通知定时调度器。
  5. 启动截图查看 API(http://0.0.0.0:8080/)。

5.6 验证

  1. 查看日志输出,确认无配置错误。
  2. 打开浏览器访问 http://127.0.0.1:8080/,应能看到截图查看器。
  3. 向 Redis Stream 投递一条测试任务:
redis-cli XADD jp_surugaya_purchase_task * task_id "task_test_001" topic "surugaya_tasks" purchase_account "acc_01" site_id "surugaya" record_video "0" payload "{\"item_list\":[{\"id\":\"m72275988725\",\"price_limit\":6500,\"number\":1}]}"

如果 Redis 设置了密码,请使用 redis-cli -a your_password ...


6. 长期后台运行(可选)

Windows 裸机环境下,可采用以下方式让服务随系统启动并保持运行:

6.1 使用任务计划程序(Task Scheduler)

  1. 创建基本任务,触发器选择“当用户登录时”或“启动时”。
  2. 操作选择“启动程序”,程序路径填写 powershell.exe
  3. 参数示例(采购 worker):
-WindowStyle Hidden -Command "cd C:\jp-deploy\jp_pruchase_zdh_5; $env:APP_ENV='prod'; uv run python -m src.main"
  1. 在“常规”选项卡中勾选“不管用户是否登录都要运行”时,服务将运行在 Session 0,可能导致 pyautogui、模板匹配、录屏等依赖桌面的功能失败。因此:

建议:采购 worker 必须运行在交互式用户会话中(本地登录或持续 RDP 会话)。抓取 API 服务可运行在非交互式账户下。

6.2 使用 NSSM

NSSM 可将任意程序封装为 Windows 服务。仅建议用于 jp_surugaya;采购 worker 因需要桌面交互,不建议使用 NSSM。


7. 升级维护

  1. 拉取最新代码(如使用 git):
cd C:\jp-deploy\jp_pruchase_zdh_5
git pull
  1. 重新同步依赖:
uv sync
  1. 重启对应 PowerShell 窗口中的进程即可。

提示:采购 worker 在 Windows 上不支持通过内置 API(POST /api/restart)重启,修改 accounts.yaml 后请手动重启进程。


8. 常见问题

8.1 uv sync 失败,提示私有索引 401

确认已设置:

$env:UV_INDEX_JERRYYAN_USERNAME="your_username"
$env:UV_INDEX_JERRYYAN_PASSWORD="your_password"

8.2 Playwright 启动浏览器失败

  • 确认已执行 uv run playwright install chromium
  • 确认已安装 Microsoft Visual C++ Redistributable
  • 若指定了 BROWSER_EXECUTABLE_PATHSURUGAYA_BROWSER_CHANNEL=chrome,确认 Chrome 已安装且路径正确。

8.3 模板匹配(Google Pay 确认按钮等)失败

  • 确认当前屏幕分辨率与 resources/images/ 下模板图的采集分辨率一致(推荐 1920x1080)。
  • 若分辨率不同,请在当前分辨率下重新截取模板图并替换原文件。

8.4 端口被占用

  • 31106 被占用:先结束旧的 python.exe / uvicorn 进程,或修改 .env 中的 SURUGAYA_APP_PORT
  • 8080 被占用:采购 worker 内置截图 API 默认使用 8080,若被其他程序占用,目前需修改源码中 src/api/server.py 的默认端口。

8.5 调用 /api/search 返回 403

检查请求头中的 Authorization: Bearer <token>.env 中的 SURUGAYA_BEARER_TOKEN 是否一致。

8.6 采购 worker 收不到 jp_surugaya 投递的任务

检查两边 Redis 配置是否指向同一主机/端口/DB,并确认 APP_ENV(采购侧)与 SURUGAYA_APP_ENV(抓取侧)一致(例如都是 prod)。

8.7 账号登录态失效

删除该账号对应的 user_data_dir 目录,重启 worker 后会重新走登录流程。


9. 安全建议

  • 不要8080 端口直接暴露到公网;截图查看器与账号配置接口均无额外应用层鉴权。
  • 31106 若需对外提供,请通过反向代理并加鉴权(如 Nginx / Cloudflare Access / 企业 VPN)。
  • SURUGAYA_BEARER_TOKEN 应使用至少 32 位的强随机字符串。
  • 敏感信息(密码、Token、SMTP 密码)只存放在 .env / accounts.yaml 中,不要提交到 Git。
  • 建议为日本站点使用稳定的日本 IP 代理,降低 Cloudflare 挑战频率。