Files
InboundVerify/CLAUDE.md
Misaka 75abbdf14c Add websocket-client to requirements; sync docs
site_anneng 的 CDP 驱动用到 websocket-client,此前 requirements.txt 缺漏,
需额外手动安装。补进 requirements.txt,并把 README/CLAUDE 里"暂未列入"的
临时提示改为"已包含"。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 22:48:07 +08:00

5.1 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

项目概览

自动登录 5 家物流承运商工作台,下载"应到 / 实到"货物数据,离线比对出应到未到 异常运单并汇总成 Excel。4 个网页站点 + 1 个 Electron 应用(安能)。

常用命令

所有 Python 一律在项目虚拟环境 .venv 中运行Windows 下可直接用 .venv/Scripts/python.exe,无需激活)。

# 安装依赖(含安能 CDP 驱动所需的 websocket-client
pip install -r requirements.txt
playwright install chromium

# 运行主程序(交互式菜单,详见 main_router 的 run_multi_site_daemon
.venv/Scripts/python.exe main_router.py

# 单站点联调:在 config.yaml 设 debug.enabled=true + debug.target_site=顺心|百世|中通|韵达|安能
#   网页站:只挂载该站;安能:只启动 Electron 应用。

# 安能独立运行(需先以 --remote-debugging-port=9222 启动「安能全网门户.exe」并手动登录
.venv/Scripts/python.exe site_anneng.py expected   # 或 actual

# 格式化(全局规范:改完 Python 必须 Black
.venv/Scripts/python.exe -m black <file.py>

# 语法自检
.venv/Scripts/python.exe -m py_compile <file.py>

没有 pytest 测试套件。 "测试"指 main_router 菜单 [8] 自动化测试 run_automation_test,按 CROSS_TEST_SEQUENCE 交叉跑通各站点流程)。

架构big picture

两套驱动模态 —— 这是理解全局的关键

  • 网页 4 站(顺心/百世/中通/韵达):main_router 用 Playwright 开 chromium 每站一个 page,流程函数签名为 xxx_download_impl(page)
  • 安能Electron 桌面应用,不走 Playwrightmain_router--remote-debugging-port=<动态空闲端口> 启动 exelaunch_anneng 通过 site_anneng.set_cdp_port 告知模块;site_anneng.py 用裸 CDPwebsocket 驱动,业务 tab 是独立 webContents。这也是 playwright-cli 接管不了安能的原因 Electron 19 / Chrome 102 不支持 Playwright 要的 setDownloadBehavior

分层:路由纯调度,站点模块自洽

  • main_router.py 只调度:启动浏览器/安能、就绪轮询、登录检测、菜单分发。 菜单项直接调 site_xxx.xxx_download(page)不关心重试/重置。
  • 每个 site_xxx.py 对外只暴露"把任务做了"的入口,内部自洽:
    • xxx_download(...) —— 公开入口,= with_retry(站点, 标签, xxx_download_impl, xxx_reset)
    • xxx_download_impl(...) —— 单次执行、无重试(自动化测试刻意调它以探测原始失败)
    • xxx_reset(...) —— 重置回初始态(网页 = page.goto(HOME_URL);安能 = 关业务 tab + 收菜单)
    • with_retry(...) —— 重试逻辑内联在每个站点模块(不抽公共组件,现阶段刻意不优化结构); 失败→重置→重试,最多 3 次(含首次),每次失败都重置(含最终放弃那次清场)
    • HOME_URL —— 站点首页 URLmain_router.SITES_CONFIG 引用它(单一来源)

导出任务队列模式(顺心/中通/韵达/安能-应到 共用)

这些站的下载是异步的:提交导出(记 export_times 时间戳)→ 跳"导出任务管理"页轮询 → 匹配本批任务 → 下载 → 合并多个临时 xlsx。

  • 匹配只按时间容差 ≤40s不校验任务标题/模块名(标题可能被站点改动;单账号无并发, 时间窗内的任务必为本批所建)。不要把标题校验加回来。
  • 轮询循环都有 300s deadline:超时 raise → 流程返回 False → 触发 with_retry 重试。
  • 例外:百世是同步下载(expect_download,无队列);安能-实到页面无导出按钮, 直接抓表格 DOM 翻页。

比对

expected_undelivered.py(菜单 [9])纯离线:读 downloads/ 下各站应到/实到 xlsx 比对生成 output/应到未到数据.xlsx(汇总 + 各站明细)。

路径

paths.pyDOWNLOAD_DIR / CONFIG_PATH / BASE_DIR 全部锚定到项目目录, 不依赖运行时 cwd——别用相对路径或 os.getcwd()

重要约定 / 易踩坑

  • 登录是手动的main_router 启动后会停在就绪轮询(READY_SELECTORS / anneng_ready 直到检测到所有站点进入工作台才进菜单。仅韵达支持凭 config.yaml 凭据自动登录。
  • 安能单实例:启动前必须先关闭已打开的安能窗口,否则调试端口起不来。
  • 安能重置绝不能用 Page.reloadreload 会让已开业务 webContents 失去 app 引用、 变成 Target.closeTarget / window.close 都杀不掉的僵尸。重置只能走 tab 条 X 关 tab + 收菜单。
  • config.yaml 已 gitignore,存放凭据 / query_days / debug / anneng.app_path 切勿提交,也别把真实凭据写进 config.example.yaml
  • 不要自动提交 / 推送:本仓库约定改动后等用户明确说"提交"再 commit/push (覆盖全局 CLAUDE.md 的 auto-push 默认)。
  • 改完 Python 文件必须跑 Black(全局规范)。