Files
FacereDataset/log.md
Knowit d874278bc5 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。
2026-04-28 20:07:40 +08:00

412 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FacereDataset 执行日志
时间倒序,最新在顶部。
---
## 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` 401cookie 已过期,但和源抓取无关)
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 MBgrep `/api/`,找到 76 个端点。关键的 `ajaxDetail = '/api/documents/{uuid}'`
5. 命中:**`https://lceda.cn/api/documents/<doc>?uuid=<doc>&path=<doc>`** 匿名 200body 是完整 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 锁定,后续新源好对齐)
### 跑批结果dev1QPS 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** 而不是 LFS10 项目共 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 会话**
核心成果:**立创 EDA Pro 工程源的 API + 加密 + 格式三层全打通**。
### 完整链路
```
1. GET /api/v4/projects/<PROJ> → branch_uuid
2. GET /api/v4/projects/<PROJ>/branches/<BRANCH> → history_uuid
3. GET /api/v4/projects/<PROJ>/branches/<BRANCH>/histories/<HIST> → {key, iv, dataStrUrl}
4. GET <dataStrUrl> (modules.lceda.cn) → 417 KB 加密 blob
5. AES-128-GCM decrypt (tag=blob[-16:]) → 417 KB gzip
6. gunzip → 2.7 MB EPRO2 源流
```
关键 headers`Editor-Version: 3.2.127` / `path: <PROJ_UUID>` / `Referer: https://pro.lceda.cn/editor` /
`Cookie: lceda_pro_session=...`(与 u.lceda.cn 的 session 不共享)
### 加密细节
- 算法: AES-128-GCM`modules.lceda.cn/pro-mgr/.../project-worker.js``this.tool.decrypt({name:"AES-GCM",iv:this.iv,tagLength:128},...)` 反查确认)
- key / iv 都是 32 hex = 16 byte
- WebCrypto 约定ciphertext || 16-byte-authTag末尾附
- 解密后 gzip magic `1f 8b 08`gunzip 得最终源流
### EPRO2 格式
立创 EDA Pro 2 的**事件溯源**格式:消息流按 `\n` 分行,每行 `{"type":...,"ticket":N,"id":...}||{payload}||[extra]`
示例样本(`无界PLUS` BOARD 文档)**8 357 条消息****40 种 type**
- PART / COMPONENT / ATTR / PIN零件与属性
- PAD / VIA / WIRE / NET / PAD_NETPCB 电气)
- LINE / POLY / RECT / ARC / CIRCLE / ELLIPSE / TEXT几何
- LAYER (1572) / LAYER_PHYS / ACTIVE_LAYER层堆叠
- FILL / POUR / POURED铺铜
- RULE / RULE_SELECTOR / RULE_TEMPLATE设计规则
### 与 Std 版对比
| | u.lceda.cn (Std) | pro.lceda.cn (Pro) |
|---|---|---|
| Cookie | `lceda_session` | `lceda_pro_session` |
| 源 API | 单一 `/api/projects/<uuid>` | 4 步 `/api/v4/...` 链 |
| 版本控制 | 无 | branches + histories |
| 加密 | 待验证 | AES-128-GCM |
| 源格式 | EasyEDA JSON扁平 | EPRO2 消息流 |
| 工具 | `easyeda2kicad.py` 第三方 | **无**现成 KiCad 转换器 |
### 落地
- 新建 `docs/sources/easyeda_pro_source.md`(完整调研,见该文档附录 A 一键重跑)
- `pyproject.toml``pycryptodome>=3.23.0`
- 清理dev1 上 `/tmp/source.blob``/tmp/source.json`(后者含 Charles 私人工程源 2.7 MB
### 待验证 / 下一步
1. **他人公开 Pro 工程**能否同样 4 步通 —— 需 HAR
2. **SCHEMATIC docType** 的 API 入口(本次只解出 BOARD
3. **多 document 枚举**project → documents 列表端点)
4. Pro 编辑器"**导出 KiCad**"功能的 API 端点(若存在,能省自写转换器的工作)
5. 对齐 `OSHWHUB_INGEST_SPEC.md`Forge 消费侧要求 `.kicad_sch` + 更严 license whitelist
### ⚠️ 安全
Charles 在聊天里粘过两次 cookieu.lceda.cn 一次 + pro.lceda.cn 一次),已写入 dev1 `~/.secrets/`
当前会话 transcript 含明文 —— 本轮验证完 Charles 应登出再重登一次,让测试期间暴露过的 session invalidate。
---
## 2026-04-23 20:10 策略大调:登录内容入场 + 云服务器 + EDA→KiCad 转换
**Claude 会话**
四项变更落实到文档(暂不写代码,等云服务器到位):
### 1. 登录态内容纳入范围
原则(`CLAUDE.md`
- 合法账号登录后抓,**禁止**盗号 / 共享号
- 凭据集中云服务器 `~/.secrets/` (mode 700)**不入** git / 日志 / metadata
- 仍不绕付费墙、不破 DRM、不抓站点明确禁抓的内容
- 换号 / 重登事件记 `docs/secrets.md`(只事件、不含值)
### 2. 云服务器(广州,待交付)
新增 plan.md §0.5 基础设施段:
- 0.5.1 机器初始化git / git-lfs / uv / python 3.11+,非 root SSH`~/.secrets/`
- 0.5.2 调度tmux/nohup 长跑 + systemd timer 增量
- 0.5.3 登录态获取cookie 导出流程
### 3. 存储分级演进
plan.md §1.4 改写:
- 前期 < 50 GB云服务器磁盘 + Gitea LFS
- 中期 50200 GB评估 Gitea 容量压力;扩容 or 分仓
- 后期 > 200 GB迁对象存储OSS / COS / MinIOGitea 只存元数据 + 指针
- 50 GB 是决策评估点,**不**过早迁移
### 4. 立创 EDA → KiCad 转换
新增 plan.md §1.6(登录态工程源抓取)+ §1.7EDA→KiCad 转换):
- §1.6 用登录账号抓 `u.lceda.cn/api/project/<uuid>` 工程源 JSON`source.json`
- §1.7 写 `scripts/convert_to_kicad.py`,候选工具 `easyeda2kicad.py`pypi活跃维护
- 批处理扫 `data/raw/oshwhub/` → 输出 `data/processed/oshwhub/<uuid>/kicad/`
-`kicad-cli sch erc / pcb drc` 做语法校验,失败样本记 `data/state/convert_failed.jsonl`
- 目的:打通 oshwhub (EasyEDA) 与 bshada/open-schematics (KiCad) 两个生态的训练语料
### 同步改动
- `docs/sources/oshwhub.md` §3.5 从"未开放"改为"需登录,纳入范围"R4 风险更新
- `README.md` 数据源表加「登录态」列,加运行环境说明
### 等待
- 广州云服务器到位 → 启动 Phase 0.5
- 账号登录凭据由 Charles 提供
---
## 2026-04-23 19:55 oshwhub.md 重写成完整调研文档
**Claude 会话**
Charles 要求把 12 493 总数验证、90 项目采样结果合进主调研文档。
`docs/sources/oshwhub.md` 重写为 9 节 + 2 附录的完整调研:
1. 一页纸 TL;DR 表
2. 站点架构
3. robots.txt 与合规
4. API 与抓取入口(列表 / SSR 详情 / 附件 CDN / 排除项 / 未开放端点)
5. **项目总数验证(新)**:三路 sort 一致 + 分页二分搜索250 × 50 = 12 500 吻合)+ grade 覆盖抽样
6. **抽样语料特征(从 oshwhub_corpus_estimate.md 并入)**:体积 / 文件类型 / license 分布
7. Schema 映射
8. 速率与礼貌
9. 目录输出约定
10. 风险与未解决7 条)
11. 附录:重跑命令、变更历史
删除重复文件 `oshwhub_corpus_estimate.md`(内容已并入 §5
---
## 2026-04-23 19:50 加入 HF bshada/open-schematics 计划
**Claude 会话**
Charles 点名把 https://huggingface.co/datasets/bshada/open-schematics 纳入第一批。
调研结论:
- 这是**已预处理**的 HF 数据集,非待爬网站
- 78 parquet shards **6.4 GB**CC-BY-4.0(商用友好)
- 10K+ 条记录,每条含 `.kicad_sch` 源 / PNG / 组件列表 / JSON / YAML / name / description
- 与 oshwhub (EasyEDA) 互补,补 KiCad 生态
决定:
- **整包镜像**到 `data/external/huggingface/bshada--open-schematics/`**不**拆 per-project 目录
-`huggingface-cli download ... --repo-type dataset`parquet 走 LFS
- 维护单独的 `datasets.md`,不与 per-project 的 `projects.md`
改动:
- 新增 `docs/sources/hf_bshada_open_schematics.md` 完整调研
- `plan.md` 加 Phase 1.5
- `README.md` 数据源表加一行
**未下载**,等拍板 6.4 GB LFS 预算。
---
## 2026-04-23 19:30 Phase 1 MVP10 个高质量 oshwhub 项目入库
**Claude 会话**:承接仓库初始化
### API 调研结论
- 列表 API`GET https://oshwhub.com/api/project?page=N&pageSize=M&sort=hot`,无鉴权,返回 12493 个项目元数据(含 grade / likes / stars / views / forks
- 详情:`GET https://oshwhub.com/<path>` 是 SSR HTML嵌入 escaped JSON`license` + `attachments[]`(每个带 name / src / size / md5 / ext / mime / download_count
- 附件 CDN`https://image.lceda.cn{src}` — 已验证无鉴权直接下载
- EasyEDA 工程源 JSON`u.lceda.cn`需登录v0.1 不抓
- 详细调研见 `docs/sources/oshwhub.md`
### 选 10 个高质量项目
判据:`grade == 4`(平台精品徽章) + `likes ≥ 100` + 应用领域多样(避免同类堆叠)+ 排除 `_copy` 派生仓。
10 个项目覆盖调试器、加热台、盖革计数器、可调电源、焊台、智能手表、USB 测电流、ZVS 感应加热、AI 开发板、红外热成像。
### MVP 爬虫
位置:`crawlers/oshwhub/crawler.py`
- `list_projects()` — 列表 API 分页
- `pick_top()` — 按 like×3 + star + fork×2 + views/100 + comments×2 + grade×50 排序
- `parse_detail_html()` — 从 SSR HTML 提取 title / license / description / attachments
- `crawl_one()` — 每项目产出:`metadata.json` / `description.md` / `cover.*` / `files/*` / `_urls.json`
- QPS ≤ 0.5`SLEEP_BETWEEN = 2.0`UA 显式声明 `FacereDataset/0.1`
### 抓取与入库
- 10/10 成功52 个附件,**524 MB**
- Gitea LFSv25.4.3 原生支持)+ 本地 `git-lfs 3.5.1`(用户态二进制装在 `~/.local/bin/`
- `.gitattributes` 规则:`data/raw/**/files/**` 一律走 LFS元数据metadata.json / description.md / \_urls.json / cover.\*)走普通 git
- 每项目目录结构:
```
data/raw/oshwhub/<uuid>/
├── metadata.json # 按 schemas/project.schema.json
├── description.md
├── cover.{jpg,png,jpeg}
├── _urls.json # 所有原始 URL 清单
└── files/* # 原始附件LFS
```
### 改动汇总
- 新增:`crawlers/oshwhub/{__init__,__main__,crawler}.py`、`schemas/project.schema.json`、`docs/sources/oshwhub.md`、`pyproject.toml`
- 修改:`.gitattributes`(缩窄到 `data/raw/**/files/**`)、`.gitignore`(移除 `data/raw/*` 排除)
### 下一步建议
1. 验收 10 个项目元数据质量(随机抽 2-3 条对照原站)
2. 决定 Phase 1.4 放量目标50500全量 12493
3. Phase 2 准备GitHub KiCad repo 调研
---
## 2026-04-23 19:40 fs-web-stream 排查 + schema 自动校验
**Claude 会话**(自主推进)
### fs-web-stream.jlc.com 定性
重新抓 `/CYIIOT/ST_LINK-V2_1` 并看 13 个 `fs-web-stream.jlc.com` 链接的上下文:全部是嘉立创服务侧栏/推广图标3D 打印、发热片、Ican、EDA 扩展广场、开源硬件平台 badge 等),**与项目本身无关**。`image.lceda.cn/attachments/` 就是项目附件的唯一入口,已确认闭环。`docs/sources/oshwhub.md` 对应章节已更新。
### scripts/validate.py
jsonschema 做两层校验:
- 默认:所有 `data/raw/**/metadata.json` 对 `schemas/project.schema.json` 的结构校验
- `--check-files`:另外验证每条 file 的本地 path 存在且 sha256 匹配
**结果**10/10 项目两项全通过。
### 新增
- `scripts/validate.py`
- `pyproject.toml` 加 `jsonschema>=4.26`
### 待决策
- 放量规模 —— 已提供实测数据:**median ≈ 110 GBp90 上界 ≈ 660 GB建议预算 150180 GB**(见 `docs/sources/oshwhub_corpus_estimate.md`
- 是否需要抓 `u.lceda.cn` 的 EasyEDA 源 JSON需登录v0.1 跳过)
---
## 2026-04-23 19:45 全量规模实测 + License 分布
**Claude 会话**(自主推进)
写 `scripts/estimate_size.py`,只抓详情 HTML 解析 `attachments[].size`,不下载;采样 90 个 hot 项目3 页 × 30
**关键发现**
- 单项目 median 9 MB / mean 22 MB / p90 54 MB / max 204 MB12493 全量 median 估算 **110 GB**p90 上界 660 GB
- **视频 (.mp4 + .qt) 占 54% 存储**!如果训练只要 PCB/原理图/BOM加 `--skip-ext mp4,qt` 存储直接砍半
- License 分布健康GPL 3.0 占 49%Public Domain 21%CC 系列 ~20%CERN/TAPR OHL 6%;样本内无闭源
- **NC (Non-Commercial) 占 ~11%**,商用场景必须过滤
结果固化到 `docs/sources/oshwhub_corpus_estimate.md`,可随时重跑验证。
### 建议
1. 存储预算定 **180 GB**median + 15% buffer
2. Phase 1.4 前给 crawler 加 `--skip-ext` 开关滤视频
3. 下游建立 license whitelist 过滤 NC / 未知
---
## 2026-04-23 18:50 仓库初始化 & 数据源调研
**Claude 会话**:初始化
完成:
- 从 `git.deepknow.site/Facere/FacereDataset` 克隆空仓到 `~/repo/FacereDataset`
- 调研立创开源平台oshwhub.com初步数据
- `robots.txt` 仅 Disallow `/posts`,其他路径允许
- 存在 `sitemap.xml`(首页 + explore + activities + market 等入口已列出)
- 项目详情页路径为 `/detail/<uuid>`(示例 `f0652fd2ae3e40b8a0ecc8dc773e3512`
- 图片 CDN`image.lceda.cn/oshwhub/pullImage/...`
- 文件下载:`fs-web-stream.jlc.com/fs-web-stream/file-operation/download/<snowflake-id>`
- 页面是 Next.js SPA首屏 HTML 800KB但数据加载具体 API 入口需要浏览器 trace留给 Phase 1.1
- 创建项目骨架:
- `README.md` — 项目简介与数据源表
- `CLAUDE.md` — 项目级 Claude 指令爬虫规约、合规红线、schema 要求)
- `plan.md` — 6 阶段建设计划Phase 0 骨架 → Phase 5 数据清洗 → Phase 6 持续运营)
- `log.md` — 本文件
- `.gitignore` — 排除 `data/raw` `data/processed` `data/state` Python 缓存等
- 目录骨架 `crawlers/ schemas/ scripts/ data/{raw,processed,state} docs/{sources,}`
- 每个空目录放 `.gitkeep`
- 首次提交 & 推送到 `origin main`
**下一步建议**
1. 拍板存储方案(本地盘 / Gitea LFS / 外部 OSS—— 影响 Phase 1.4 放量时机
2. 目标规模1 万 / 10 万 / 全量)
3. 决定是否保留二进制附件或只存 URL
4. 完成上述 3 项后启动 Phase 1.1(用 `chrome-devtools` MCP 录 oshwhub 的 network trace 定位真实 API