Add EasyEDA Std project source ingestion (10 boards backfilled)
打通 oshwhub origin=std 项目的工程源(schematic + PCB dataStr)抓取链路。原
plan.md §1.6 假设需要登录,实测 lceda.cn/api/documents/<doc>?uuid=<doc>&path=<doc>
对公开项目匿名可访问 —— 无需 cookie,无账号封禁风险。
调研:4 轮探测留痕在 data/state/std_probe[1-5]/(gitignored);翻 Std 编辑器
v6.5.51 的 main.min.js bundle 找到 ajaxDetail 端点;按 docType 区分两种
响应 shape(schematic 项目视图 vs PCB 文档视图)。
Crawler:
- make_source_client() 用浏览器 UA + lceda.cn/editor Referer,因为
oshwhub /api/project/<uuid> 端点拒绝 FacereDataset/0.1 UA(CLAUDE.md
UA 例外条款:目标站主动封自定义 UA + 公开静态资源)
- fetch_std_source(): 项目元 → version_documents → 逐文档 dataStr → 落
source/<doc>.json + source/manifest.json
- --with-source(爬新项目时一并抓源)/ --backfill-source(仅扫已有)
- QPS ≤ 0.2 (SLEEP_SOURCE = 5s) 自律
Schema: 加 source_format / source_path / source_documents / editor_version
(前 3 进 enum 锁定,便于后续 Pro / KiCad 源对齐)。
回填结果:10/10 成功,45 个文档,33.2 MB;schema validate 全通。
docTypes 主要是 1 (schematic) 与 3 (pcb);USB 电压电流表只有 PCB 文档(4 个:
主板+盖板+底板+面板,作者未上传原理图源)。
完整调研:docs/sources/easyeda_std_source.md。
This commit is contained in:
101
log.md
101
log.md
@@ -4,6 +4,107 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-28 19:50 Std 工程源链路打通 + 10 板子 schematic/PCB 全部回填
|
||||
|
||||
**Claude 会话**
|
||||
|
||||
承接计划:把已抓 10 个板子的"需登录才能下载的原理图 + PCB"补齐。
|
||||
|
||||
### 关键发现:根本不需要登录
|
||||
|
||||
10 个板子全是 `origin: "std"`(EasyEDA 标准版)。原 `plan.md §1.6` 假设源数据要登录 — 实际**公开项目的 `dataStr` 匿名可访**。
|
||||
|
||||
调研路径(4 轮探测,留痕在 `data/state/std_probe[1-5]/`):
|
||||
1. `/api/user`、`/api/projects` 401(cookie 已过期,但和源抓取无关)
|
||||
2. **`oshwhub.com/api/project/<uuid>` 浏览器 UA 匿名 200**,返回 `version_documents[]`(含 doc uuid + master + history chain)
|
||||
3. `modules.lceda.cn/histories/<hash>.json` 仍 403(与 Pro 同结构,但 Std 不走这条路)
|
||||
4. 翻 Std 编辑器 `/editor/6.5.51/js/main.min.js`(5 MB)grep `/api/`,找到 76 个端点。关键的 `ajaxDetail = '/api/documents/{uuid}'`
|
||||
5. 命中:**`https://lceda.cn/api/documents/<doc>?uuid=<doc>&path=<doc>`** 匿名 200,body 是完整 EasyEDA JSON(`dataStr.{head,canvas,shape,BBox,colors[layers,objects,DRCRULE,...]}`)
|
||||
|
||||
**两种响应 shape**(按 docType 区分):
|
||||
- docType=1 (Schematic):返"项目视图",`result.schematics[0].dataStr`
|
||||
- docType=3 (PCB):返"文档视图",`result.dataStr` 直接在顶层
|
||||
|
||||
### 与 Pro 的差异
|
||||
|
||||
| 维度 | Std (本轮) | Pro (`docs/sources/easyeda_pro_source.md`) |
|
||||
|---|---|---|
|
||||
| 鉴权 | **无需** | `lceda_pro_session` 必须 |
|
||||
| 加密 | **无** | AES-128-GCM + gzip |
|
||||
| 源格式 | 扁平 EasyEDA JSON(`shape[]`) | EPRO2 消息流(事件溯源) |
|
||||
| 多 doc | `version_documents[]` 逐个 GET | `/structures` + history chain 重放 |
|
||||
|
||||
### 实施
|
||||
|
||||
- `docs/sources/easyeda_std_source.md`:完整调研(含 dataStr 字段、抓取伪代码、附录重跑脚本)
|
||||
- `crawlers/oshwhub/crawler.py`:
|
||||
- 新增 `make_source_client()` —— 浏览器 UA + Referer,规避 oshwhub `/api/project/<uuid>` 端点对 `FacereDataset/0.1` UA 的 reject(在 commit message 注明 UA 例外原因)
|
||||
- 新增 `fetch_std_source()`:项目 → version_documents → 逐文档 dataStr → 落 `source/<doc>.json` + `source/manifest.json`
|
||||
- 新增 `--with-source` 标志(爬新项目时一并抓源)和 `--backfill-source`(仅扫已有项目补源)
|
||||
- QPS ≤ 0.2(`SLEEP_SOURCE = 5.0s`)
|
||||
- `schemas/project.schema.json`:加 `source_format`/`source_path`/`source_documents`/`editor_version` 字段(前 3 个进 enum 锁定,后续新源好对齐)
|
||||
|
||||
### 跑批结果(dev1,QPS 0.2)
|
||||
|
||||
10/10 全成功;schema 验证 10/10 pass:
|
||||
|
||||
| 项目 | docs | docTypes | 大小 | editor |
|
||||
|---|---|---|---|---|
|
||||
| ST-LINK V2-1 | 2 | [1,3] | 682 KB | 6.5.39 |
|
||||
| USB 电压电流表 | **4** | **[3]** | 1.2 MB | 6.5.15 |
|
||||
| 红外热成像 | 2 | [1,3] | 1.6 MB | 6.5.22 |
|
||||
| t12-858d 焊台 | **11** | [1,3] | 6.1 MB | 6.5.15 |
|
||||
| 加热台量产计划 | 6 | [1,3] | **12.0 MB** | 6.5.43 |
|
||||
| ESP32-S3 智能手表 | 4 | [1,3] | 1.4 MB | 6.5.41 |
|
||||
| RT300-MKV 可调电源 | 3 | [1,3] | 3.3 MB | 6.5.23 |
|
||||
| YuzuMaix V831 | 4 | [1,3] | 5.4 MB | 6.5.37 |
|
||||
| 盖革计数器 | 6 | [1,3] | 1.2 MB | 6.5.47 |
|
||||
| ZVS 感应加热 | 3 | [1,3] | 990 KB | 6.5.40 |
|
||||
|
||||
**合计**:45 个文档 / 33.2 MB(中位 ~1.5 MB / 项目,附件主体约为附件主流量的 6%)
|
||||
|
||||
观察:
|
||||
- USB 电压电流表只有 PCB 文档(4 个:主板 + 盖板 + 底板 + 面板,作者未上传原理图源)
|
||||
- t12 焊台 11 个文档(拆得碎,估计含多个独立模块)
|
||||
- editor 版本散布在 6.5.15 - 6.5.47(取决于作者上一次保存项目时的客户端版本)
|
||||
|
||||
### 落盘结构(per project)
|
||||
|
||||
```
|
||||
data/raw/oshwhub/<uuid>/
|
||||
├── metadata.json # ★ 新增字段:source_format/source_path/source_documents/editor_version
|
||||
├── description.md
|
||||
├── cover.*
|
||||
├── _urls.json
|
||||
├── files/ # 用户附件(已存在,LFS)
|
||||
└── source/ # ★ 新:EasyEDA Std 工程源
|
||||
├── manifest.json # 文档清单 + 抓取时间 + upstream version_documents 留档
|
||||
└── <doc_uuid>.json # 完整 dataStr 响应(普通 git,文件 1-5 MB 量级)
|
||||
```
|
||||
|
||||
`source/*.json` **走普通 git** 而不是 LFS(10 项目共 33 MB 完全够用;放量时再考虑加 LFS 规则)。
|
||||
|
||||
### 安全 / 合规
|
||||
|
||||
- 无登录态、无凭据使用 → 无账号封禁风险,无 cookie 泄漏顾虑
|
||||
- UA 例外:源抓取使用浏览器 UA 而非 `FacereDataset/0.1`,原因写入 `docs/sources/easyeda_std_source.md §3` 与本 commit message
|
||||
- License:与原项目附件相同的 license 字段已在 metadata,下游 whitelist 过滤逻辑不变
|
||||
|
||||
### 未决 / 下一步
|
||||
|
||||
1. dev1 上的 `~/.secrets/lceda.json` cookie 已过期(XSRF 4-22 失效,今天 4-28),但**本任务已不依赖**它。是否保留待定 —— Pro 流程可能仍要
|
||||
2. `easyeda2kicad.py` 转换:现有 45 个 dataStr 是关键测试样本,可立刻跑(`plan.md §1.7`)
|
||||
3. 放量决策:从 10 → 50 → 全量 12,493 时,按 33 MB / 10 ≈ 3.3 MB/proj 估算,全量源 ~40 GB(不含附件本体)
|
||||
4. 多账号轮询、Pro 链路打通仍是 `plan.md §1.6` 的开放项(仅当遇到 Pro 项目时才用得上)
|
||||
|
||||
### 改动清单
|
||||
|
||||
- 新增:`docs/sources/easyeda_std_source.md`、`scripts/probe_std_api[1-5].py`、`data/raw/oshwhub/<uuid>/source/`(10 项目)
|
||||
- 修改:`crawlers/oshwhub/crawler.py`、`schemas/project.schema.json`、10 项目的 `metadata.json`
|
||||
- 待人工:`projects.md` 重生成(脚本未跑);`plan.md §1.6` 状态从 ⏳ → ✅,§1.7 unblocked
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-24 00:25 打通 pro.lceda.cn 工程源完整链 + EPRO2 格式解析
|
||||
|
||||
**Claude 会话**
|
||||
|
||||
Reference in New Issue
Block a user