Add EasyEDA Pro 2.x legacy source ingestion (5/5 batch closure)
补齐前一批失败的 2 个 legacy Pro 项目(立创·泰山派 RK3566、立创·梁山派),
打通 Pro 2.x 旧版工程的源抓取链路。结合上一 commit 的 modern Pro 3.x
路径,本仓库 5/5 Pro 项目 EPRO2/dataStr 全部端到端打通。
Pro 2.x 与 Pro 3.x 是两个完全不同的存储模型:
- Pro 3.x:git-style branch + linear history chain,AES-128-GCM 加密的
EPRO2 增量消息流,按 history 重放(已在前一 commit 打通)
- Pro 2.x:无 branch / 无 history。文档以 EasyEDA Std plaintext dataStr
存储(同 ["DOCTYPE","SCH","1.1"] 格式),按 doc UUID 通过
/api/v2/documents/lists 批量 GET,主体无加密,只组件库走 AES
Pro 2.x 抓取链由 HAR (tmp/prodownload3.har, 178 请求) 反推:
GET /api/v4/projects/<P> → boards: [{sch, pcb, name}]
GET /api/projects/<P>/ticket?uuid=&g_ticket=-1
→ 完整项目 manifest
POST /api/schematic/lists {uuids:[<sch>]} → sort: [{uuid:<sheet>}]
POST /api/v2/documents/lists {uuids,docType:1} → schematic plaintext
POST /api/v2/documents/lists {uuids,docType:3} → PCB plaintext
POST /api/coppers/search {paths} → 铺铜层
POST /api/textpath/search {paths,project_uuid}→ 字体/文字
POST /api/v2/resources/search {hash,project_uuid} → BLOB 图片
实现:
- crawlers/oshwhub/crawler.py:
- fetch_pro_source() refactor 成 dispatcher,先 GET project meta
检查 branch_uuid,null 即旧版走 _fetch_pro_legacy(),非空走
_fetch_pro_modern()
- _fetch_pro_legacy() 新增(按上面 9 步流程拉所有 doc + 辅助层)
- _pro_post_json() POST helper(与 _pro_get_json 对称)
- schemas/project.schema.json: source_format enum 加 easyeda-pro-legacy
- docs/sources/easyeda_pro_source.md rev 4: §1.1 旧版 vs 新版判别表更新、
§2.7 新增旧版抓取流程 + 实测数据
落盘约定(旧版):
source/ticket.json 完整 manifest
source/<sheet_uuid>.json 每张原理图(含 dataStr)
source/pcb_<pcb_uuid>.json 每块 PCB
source/coppers.json/textpath.json/blobs.json 辅助 PCB 层资源
source/manifest.json 索引
实测:
立创·梁山派 editor=2.1.30, 2 sheets+1 pcb, 1.0 MB, 78 sym/191 fp/128 dev
立创·泰山派 RK3566 editor=2.1.40, 29 sheets+1 pcb, 0.8 MB, 299 sym/524 fp/295 dev
旧版项目体量比新版小两个数量级(梁山派 1 MB vs RK3576 66 MB)—— 没有
增量 history,组件库走单独端点,本身就是当前快照。
5/5 Pro 项目终极汇总:
X86 主板 easyeda-pro 3.2.15 7374 docs / 481 MB
泰山派 RK3566 easyeda-pro-legacy 2.1.40 30 docs / 0.8 MB
梁山派 easyeda-pro-legacy 2.1.30 3 docs / 1.0 MB
220V 桌面电源 easyeda-pro 3.2.69 771 docs / 26 MB
ESP-VoCat easyeda-pro 3.2.91 278 docs / 7.5 MB
共 8456 docs / ~516 MB plain。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,14 +45,17 @@
|
||||
|
||||
| 维度 | Pro 2.x 旧版 | Pro 3.x 新版 |
|
||||
|---|---|---|
|
||||
| `editorVersion` | "2.1.40" 等 | "3.2.91" / "3.2.127" |
|
||||
| `editorVersion` | "2.1.30" / "2.1.40" 等 | "3.2.15" / "3.2.69" / "3.2.91" / "3.2.127" 等 |
|
||||
| `branch_uuid` | **null**(无分支模型) | UUID(有 main 分支) |
|
||||
| 文档定位 | 项目 meta 的 **`boards: [{sch, name, pcb}]`** 直接指向 doc UUID | `/structures` 返回多 document 树 |
|
||||
| 历史链 | **不存在**(无 `/branches/<B>/histories/<H>` 端点) | 完整 git-style chain,本节后续描述 |
|
||||
| 状态 | ⏳ **本爬虫暂不支持**;HAR 待录 | ✅ 已打通 |
|
||||
| 实例 | `7360e73d...`(立创·泰山派RK3566)、`0c467598...`(立创·梁山派) | `2507dcb6...`(立创·泰山派RK3576)、`b7784066...`(X86电脑主板)、`ba64bd6f...`(ESP-VoCat) |
|
||||
| 文档定位 | 项目 meta 的 **`boards: [{sch, name, pcb}]`** + ticket 端点 manifest | `/structures` 返回多 document 树 |
|
||||
| 历史链 | **不存在** | 完整 git-style linear chain |
|
||||
| 文档存储 | **plaintext** dataStr(同 Std `["DOCTYPE","SCH","1.1"]\n[HEAD,...]`),按 doc UUID 批量 GET | AES-128-GCM 加密的 EPRO2 增量消息流,按 history 重放 |
|
||||
| 加密 | 仅组件库(symbols/devices)走 AES,文档本身明文 | 全部 history blob 都加密 |
|
||||
| 实例 | `7360e73d...`(RK3566 / 2.1.40 / 30 docs)、`0c467598...`(梁山派 / 2.1.30 / 3 docs) | `2507dcb6...`(RK3576)、`b7784066...`(X86 / 7374 docs)、`ba64bd6f...`(ESP-VoCat / 278 docs) |
|
||||
| 状态 | ✅ 已打通(HAR `tmp/prodownload3.har` 反推) | ✅ 已打通 |
|
||||
| schema source_format | `easyeda-pro-legacy` | `easyeda-pro` |
|
||||
|
||||
**判别**:先 GET `/api/v4/projects/<P>`,看 `branch_uuid` 是否非空。`null` 即旧版;记录跳过原因到 `data/state/oshwhub_excluded.jsonl`。**旧版工程的 sch/pcb document UUID 在 `boards[]` 字段里**(每个 board = 一对 sch+pcb),但访问端点未知 —— 候选探测:`/api/documents/<doc>`(实测 401,需要不同 cookie scope)、`/api/v4/projects/<P>/snapshots`(200 但返回的是 project meta 而非 doc)。
|
||||
**判别**:先 GET `/api/v4/projects/<P>`,看 `branch_uuid` 是否非空。`null` 即旧版,走 §2.7 的旧版抓取路径;非空走 §2.1-§2.6 的新版路径。`crawlers/oshwhub/crawler.py:fetch_pro_source()` 是 dispatcher,根据 `branch_uuid` 自动分流到 `_fetch_pro_modern()` 或 `_fetch_pro_legacy()`。
|
||||
|
||||
---
|
||||
|
||||
@@ -233,6 +236,51 @@ Accept: application/json
|
||||
|
||||
chain 只有 1 条就包含整个 project,因为只有 1 个 document。
|
||||
|
||||
### 2.7 Pro 2.x 旧版抓取(无 branch / 无 history chain)
|
||||
|
||||
适用于 `branch_uuid: null` 的工程(`editorVersion` 形如 `2.1.40`)。文档以 **EasyEDA Std plaintext dataStr** 形式存储,按 UUID 批量 GET,不需要解密 / 解压 / 重放。
|
||||
|
||||
#### 流程
|
||||
|
||||
```
|
||||
GET /api/v4/projects/<P> → boards: [{sch, pcb, name}]
|
||||
GET /api/projects/<P>/ticket?uuid=<P>&g_ticket=-1 → manifest: {schematics, schs, pcbs, coppers, textpath, blobs, symbols, footprints, devices, ...}
|
||||
POST /api/schematic/lists {uuids:[<sch>]} → 父 schematic 容器,含 sort: [{uuid: <sheet>, ticket}, ...]
|
||||
POST /api/v2/documents/lists {uuids:[<sheets>], docType:1} → 每个 sheet 的 dataStr 明文
|
||||
POST /api/v2/documents/lists {uuids:[<pcbs>], docType:3} → 每个 PCB 的 dataStr 明文
|
||||
POST /api/coppers/search {paths:[<copper_paths>]} → 铺铜数据(PCB 增量层)
|
||||
POST /api/textpath/search {paths:[<textpath_paths>], project_uuid, path} → 字体 / 文字路径
|
||||
POST /api/v2/resources/search {hash:[<sha256>], project_uuid} → BLOB(嵌入图片等)
|
||||
POST /api/v2/components/searchByIds {uuids:[<symbol_uuids>]} → 元件符号定义(含 dataStrId/key/iv,AES 加密的 lib 数据;可选)
|
||||
POST /api/devices/searchByIds {uuids:[<device_uuids>]} → 元件库 metadata
|
||||
```
|
||||
|
||||
#### 必需 headers
|
||||
|
||||
与 §2.5 相同(`Editor-Version` / `path: <PROJ_UUID>` / `Cookie`)。
|
||||
|
||||
#### 实测数据
|
||||
|
||||
| 工程 | editorVersion | sheets | pcbs | symbols | footprints | devices | blobs | coppers | size |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| 立创·梁山派 | 2.1.30 | 2 | 1 | 78 | 191 | 128 | 1 | 29 | 1.0 MB |
|
||||
| 立创·泰山派 RK3566 | 2.1.40 | 29 | 1 | 299 | 524 | 295 | 32 | 0 | 0.8 MB |
|
||||
|
||||
**关键观察**:
|
||||
- 旧版项目体量比新版小**两个数量级**(梁山派 1 MB vs RK3576 66 MB plain)—— 因为没有 history 增量、组件库走单独端点、本身就是当前快照。
|
||||
- `manifest_ticket['schematics']` ↔ schematic CONTAINER(板级"原理图"实体);`manifest_ticket['schs']` ↔ 单个 SHEET(一页图纸)。`boards[].sch` 指向前者,需要 schematic/lists 一步把 sort 拆出 sheet UUIDs。
|
||||
- 抓 plaintext docs 后,**无需** AES 解密(这点跟 Std 一样)。但 symbols/devices 端点返回的 lib 数据**仍然是 AES 加密的 dataStrId blob**,跟 Pro 3.x 同方案;如需还原 lib 内容需照 §2.3 解密流程。
|
||||
|
||||
#### 落盘约定
|
||||
|
||||
- `source/ticket.json` — 完整 manifest_ticket(保留以备后续 lib 重建)
|
||||
- `source/<sheet_uuid>.json` — 每张原理图(含 `dataStr` 字段)
|
||||
- `source/pcb_<pcb_uuid>.json` — 每块 PCB
|
||||
- `source/coppers.json` / `source/textpath.json` / `source/blobs.json` — 辅助层资源
|
||||
- `source/manifest.json` — 索引 + structure_summary
|
||||
|
||||
实现:`crawlers/oshwhub/crawler.py:_fetch_pro_legacy()`。
|
||||
|
||||
#### B. 大项目 `泰山派3M (RK3576)`(36 documents)
|
||||
|
||||
| 步骤 | 数值 |
|
||||
@@ -491,3 +539,4 @@ PY
|
||||
| 2026-04-24 (rev 1) | 首版:单 history 4 步链 + AES-128-GCM + gzip + EPRO2 消息流(40 种 types 覆盖 BOARD 全要素) |
|
||||
| 2026-04-24 (rev 2) | 加入 `/structures` 枚举、`/projects/branches/histories?...` 批量 chain 端点、完整重放流水线;大项目(泰山派 36 docs / 35 histories / 66 MB)实测;对他人 public Pro 项目已验证;29 条 `/api/v4/` 端点清单 |
|
||||
| 2026-04-28 (rev 3) | HAR 实测:`/branches/{branch}/histories/{head}` 即返回整条 chain(无需走 `?limit=N` 批量端点);落地 `crawlers/oshwhub/crawler.py:fetch_pro_source` 端到端打通(5 项目批量抓 EPRO2);schema docType 兼容 string 取值 + 增 message_count 字段 |
|
||||
| 2026-04-28 (rev 4) | HAR `prodownload3.har` 反推 **Pro 2.x 旧版抓取链**:`/api/projects/<P>/ticket` + `/api/v2/documents/lists` 批量端点(plaintext dataStr)+ supplementary coppers/textpath/blobs/components/devices;新增 `_fetch_pro_legacy()` + 在 `fetch_pro_source()` 按 `branch_uuid` 自动 dispatch;schema source_format enum 增 `easyeda-pro-legacy`;5/5 Pro 项目(3 modern + 2 legacy)全部打通 |
|
||||
|
||||
Reference in New Issue
Block a user