Add README and CLAUDE.md project docs
- README.md:面向使用者的项目说明(站点/流程、环境、配置、运行、架构、输出)。 - CLAUDE.md:面向后续开发的关键命令与非显而易见的跨文件架构与约定。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
90
CLAUDE.md
Normal file
90
CLAUDE.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# 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`,无需激活)。
|
||||
|
||||
```bash
|
||||
# 安装依赖(安能的 CDP 驱动还需 websocket-client,requirements.txt 暂未列入)
|
||||
pip install -r requirements.txt
|
||||
pip install websocket-client
|
||||
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 桌面应用,**不走 Playwright**。`main_router` 以
|
||||
`--remote-debugging-port=<动态空闲端口>` 启动 exe(`launch_anneng`),
|
||||
通过 `site_anneng.set_cdp_port` 告知模块;`site_anneng.py` 用裸 CDP(websocket)
|
||||
驱动,业务 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` —— 站点首页 URL,`main_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.py` 把 `DOWNLOAD_DIR` / `CONFIG_PATH` / `BASE_DIR` 全部锚定到项目目录,
|
||||
**不依赖运行时 cwd**——别用相对路径或 `os.getcwd()`。
|
||||
|
||||
## 重要约定 / 易踩坑
|
||||
|
||||
- **登录是手动的**:`main_router` 启动后会停在就绪轮询(`READY_SELECTORS` / `anneng_ready`),
|
||||
直到检测到所有站点进入工作台才进菜单。仅韵达支持凭 `config.yaml` 凭据自动登录。
|
||||
- **安能单实例**:启动前必须先关闭已打开的安能窗口,否则调试端口起不来。
|
||||
- **安能重置绝不能用 `Page.reload`**:reload 会让已开业务 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**(全局规范)。
|
||||
Reference in New Issue
Block a user