Files
FacereDataset/docs/sources/oshwhub.md
Zhang Jiahao b0ddcf3f14 Allow login content; plan cloud infra, storage tiers, EDA→KiCad conversion
Why:
- 策略调整:登录后才能访问的内容从"禁止"改为"纳入本项目范围",
  同时明确凭据管理红线(合法账号、不入 git、云服务器隔离)。
  解锁 u.lceda.cn 工程源 JSON,这是训练数据质量的关键升级。
- 计划中"存储"和"运行环境"一直模糊,现在按 Charles 提供的广州云服务器
  + 存储分级演进(Gitea LFS → 对象存储)给出清晰路径。
- 打通 oshwhub (EasyEDA) 与 bshada/open-schematics (KiCad) 两个生态,
  需要一个 EDA→KiCad 批转换脚本。先把它纳入 plan,等拿到工程源再实现。

What:
- CLAUDE.md: 登录态条款从"不抓"改为"合法账号可抓",凭据管理写死在
  ~/.secrets/,事件记 docs/secrets.md;合规红线同步更新
- plan.md §0.5: 新增 基础设施段(机器初始化 / 调度 / 登录态获取)
- plan.md §1.4: 存储分级演进(< 50 GB 云盘,50-200 GB 评估,> 200 GB 迁对象存储)
- plan.md §1.6: 登录态抓 u.lceda.cn 工程源
- plan.md §1.7: scripts/convert_to_kicad.py 批处理,候选 easyeda2kicad.py
- plan.md 风险表: 加账号封禁 / 转换失败 / 云服务器单点故障三条
- docs/sources/oshwhub.md: u.lceda.cn 从"未开放"移到"需登录,已纳入范围"
- README.md 数据源表: 加"登录态"列 + 运行环境说明
- log.md: 本次策略变更记录

未改:未新增 docs/infra.md(等机器到位 + 真实细节后再写),scripts/convert_to_kicad.py
尚未实现(等拿到工程源样本再实现)。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 20:57:30 +08:00

14 KiB
Raw Permalink Blame History

立创开源硬件平台 (oshwhub.com) — 数据源调研

平台:立创开源硬件平台(嘉立创 EDA / 深圳创电优选科技有限公司) URLhttps://oshwhub.com 首版调研2026-04-23 维护:每次爬虫新发现或数据结构变更须更新本文件


TL;DR

指标 备注
公开项目总数 12 493 已发布到开源广场的项目(见 §4 验证)
抓取复杂度 低 — 中 列表 API 开放,详情走 SSR HTML 解析
License 主流 GPL 3.0 (49%) / Public Domain (21%) / CC 系列 (20%) / CERN·TAPR OHL (6%) 采样 90 项目,见 §5.3
单项目体积中位数 9 MBmean 22 MB, p90 54 MB, max 204 MB §5.1
全量存储估算 110 GB (median) / 660 GB (p90 上界) §5.1 推算
反爬风险 列表 API 无 rate-limit 实测,建议 QPS ≤ 0.5 自律
登录态要求 匿名够用但登录更全 公开元数据 + 附件走匿名端点(见 §3工程源 JSON 需登录(见 §3.5 & plan.md §1.6
当前已入库 10 项目 / 52 附件 / 535 MB 见仓库 projects.md

爬虫实现crawlers/oshwhub/crawler.py


1. 站点架构

  • Next.js App Router SPA。首页、列表页由客户端 fetch 渲染(首屏 HTML 无卡片 DOM详情页 /<user>/<slug>/detail/<uuid>SSR,首屏 HTML 已包含完整元数据与附件列表
  • axios baseURL = https://oshwhub.com(见 /_next/static/chunks/8661-*.js
  • CDN
    • 封面 / 附件:https://image.lceda.cn
    • 嘉立创服务侧栏图标:https://fs-web-stream.jlc.com(与项目内容无关,见 §3.4

2. robots.txt 与合规

User-agent: *
Disallow: /posts
Sitemap: https://oshwhub.com/sitemap.xml

/detail//explore/api/project允许抓取。本项目所有抓取严格按 robots 执行。


3. API 与抓取入口

3.1 项目列表 — 主入口

GET https://oshwhub.com/api/project?page=N&pageSize=M&sort=hot
参数 含义 备注
page 页码(从 1 起)
pageSize 页大小 最大 50;超过返回空
sort 排序 hot(默认)/ like / new

返回:

{
  "success": true,
  "code": 0,
  "result": {
    "page": 1,
    "pageSize": 50,
    "total": 12493,
    "totalPage": 250,
    "lists": [ /* project items */ ]
  }
}

每条 list item 字段

字段 类型 说明
uuid string (32 hex) 项目全局 ID
name string 项目名
introduction string 简介 (≤ 200 字)
path string <username>/<slug>,用于拼详情 URL
owner object {uuid, username, nickname, avatar, team}
count object {fork, star, like, views, watch}
grade int 质量档位(观察到 044 = 精品徽章)
thumb string 封面(以 //image.lceda.cn//images/ 开头)
tags string[] 可能为空
created_at ISO 8601 项目创建时间EDA 编辑器创建)
updated_at ISO 8601 项目上次更新时间
oshwhub_publish_at ISO 8601 发布到开源广场的时间(sort=new 按此排)
public, publish bool 本 API 返回的记录里恒为 true
comments_count int

陷阱sort=new 实际按 oshwhub_publish_at 排,不是 created_atpage=1 下最早可能看到 created_at: 2021-01-17 的项目(因为它刚发布到广场)。

3.2 项目详情 — SSR HTML 解析

GET https://oshwhub.com/<path>        # 例https://oshwhub.com/CYIIOT/ST_LINK-V2_1
GET https://oshwhub.com/detail/<uuid> # 等价

HTML 内嵌 escaped JSONNext.js RSC payload关键字段位置

<title>自制ST-LINK V2-1开源版本 - 立创开源硬件平台 - 深圳创电优选科技有限公司</title>
<meta name="description" content="最近迷上了攻城狮工具的制作..." />
...
<!-- 正文 HTML 中某处(在 RSC 字符串里,用 \" 转义):-->
\"license\":\"GPL 3.0\"
\"creator\":{\"uuid\":\"367b6ee2c2114a459898e14b1268a641\"}
\"attachments\":[
  {\"id\":1,\"uuid\":\"83ade303...\",\"name\":\"ST-Link V2.1官方图纸.pdf\",
   \"src\":\"/attachments/2020/7/mRn5hQ....pdf\",
   \"mime\":\"application/pdf\",\"ext\":\"pdf\",
   \"size\":183323,\"md5\":\"bdb976690426a0e3216ad3aacd9878cc\",
   \"download_count\":3720},
  ...
]

提取流程见 crawlers/oshwhub/crawler.py::parse_detail_html

  1. <title> → 项目标题(去后缀)
  2. <meta name="description"> → 简介
  3. re.search(r'\\"license\\":\\"([^\\"]+)\\"') → license 字段
  4. 定位 \\"attachments\\":[,括号平衡法截出数组,反转义 \""json.loads

3.3 附件下载 CDN

https://image.lceda.cn{attachments[].src}
# 例https://image.lceda.cn/attachments/2020/7/mRn5hQ....pdf
  • HTTP 200无鉴权(直接 curl 即可)
  • 覆盖类型PDF / ZIP / RAR / 7z / MP4 / CSV / BIN / JSON / JPG / PNG 等用户自传全类型
  • 这是项目用户文件的唯一入口,已穷举排查确认

3.4 已排查的「非项目源」路径

  • https://fs-web-stream.jlc.com/fs-web-stream/file-operation/download/<snowflake-id> — 详情页 HTML 里会出现这类 URL十几个每页但 context 都是嘉立创服务侧栏/推广图标

    • "嘉立创 3D 打印" icon
    • "开源硬件平台" badge
    • "EDA 扩展广场" banner
    • "Ican" / "发热片" 等产品线图标

    与项目本身无关,爬虫应跳过。

3.5 需登录的端点(纳入本项目范围,待 Phase 1.6 实现)

端点 现象(匿名) 登录后预期
/api/project/<uuid> {"code":104001,"success":false} 返回项目完整元数据(待验证)
u.lceda.cn/api/projects HTTP 401 "尚未登录" EasyEDA 编辑器的工程列表
u.lceda.cn/api/project/<uuid> 302 重定向 工程源 JSONschematic + PCB + 组件)— 训练数据最关键的一层
/api/search/* 空响应 可能可用(待验证)

策略(按 CLAUDE.md "登录态"条款):使用合法账号登录后抓,账号放云服务器 ~/.secrets/QPS ≤ 0.2 自律防封号,凭据不入 git。

实施见 plan.md §1.6;抓到的源 JSON 会走 scripts/convert_to_kicad.py§1.7)统一到 KiCad 格式。


4. 项目总数验证

API 报告 total: 12493(三种 sort 下一致),采用两步交叉验证:

4.1 三路 sort 一致性

for sort in hot new like; do
  curl -s "https://oshwhub.com/api/project?page=1&pageSize=1&sort=$sort" \
    | python3 -c "import sys,json;print(json.load(sys.stdin)['result']['total'])"
done
# 三次输出均为 12493

4.2 分页边界二分搜索

pageSize=50 二分查找最后一页有数据的页号:

page  2000 -> 0  items     page  253 -> 0
page   687 -> 0              page  251 -> 0
page   468 -> 0              last real ≈ 250

250 × 50 = 12 500,与 total=12493(最后一页 43 条不满)完全吻合。

4.3 覆盖范围抽样

sort=new 翻到中间几页,grade 档位分布:

观察到的 grades
1 全 grade=4精品
100 grade=3
200 grade=2
300 grade=2
1000 grade=0

结论12 493 包含所有档位04不是仅精品子集。这就是"立创开源广场"的公开可下载全量。

:该数字不等于立创 EDA 编辑器里所有用户工程的总数——私有草稿、未发布工程不在 API 范围内也不应被本项目爬取。12 493 是合规可抓的上限。


5. 抽样语料特征90 项目实测)

重跑命令uv run python scripts/estimate_size.py --pages 3 --page-size 30 --sort hot 采样方法:只解析详情 HTML 的 attachments[].size 求和,不下载附件 采样日期2026-04-23

5.1 单项目体积分布

指标 附件数 体积
mean 3.1 22.2 MB
median 2 9.0 MB
p90 54.2 MB
max 15 204.5 MB

90 个样本合计 2001 MB。偏差说明:样本来自 sort=hot top 90偏向有人气、附件齐的项目长尾低人气、无附件项目的中位数会更低。

全量 12 493 项目存储推算

基数 估算
mean × total 271 GB
median × total 110 GB ← 推荐规划值
p90 × total 662 GB ← 容量上界

建议预算150180 GBmedian + 15% buffer+ 考虑 hot 偏差修正后向下取)。

5.2 文件类型分布(按字节)

后缀 样本总量 占比
.mp4 1 029 MB 51%
.zip 676 MB 34%
.rar 72 MB 4%
.qt 66 MB 3%
.pdf 32 MB 2%
.bin 27 MB 1%
.jpeg 26 MB 1%
.7z 10 MB <1%

关键洞察:视频(.mp4 + .qt ≈ 54%)占存储一半。训练语料如果主要用 PCB / 原理图 / BOM / 叙事,加 --skip-ext mp4,qt,mov,avi直接省一半存储。

5.3 License 分布90 项目样本)

License 计数 占比
GPL 3.0 44 49%
Public Domain 19 21%
CC BY-NC-SA 4.0 5 6%
CERN Open Hardware License 4 4%
CC BY-NC-SA 3.0 3 3%
CC BY-SA 4.0 2 2%
TAPR Open Hardware License 2 2%
CC-BY-NC-SA 3.0 2 2%
其他 CC 变种 2 2%

全部开源 / 公共领域,样本中无闭源。但注意:

  • 49% GPL 3.0:训练模型无直接违反,但下游若发布模型权重 + 数据集作为 derivative work保守应沿用 GPL 或评估 scope

  • ~11% NCNon-Commercial:商用场景必须过滤剔除

  • 全量里 license: "unknown"(作者未选)比例可能更高,下游按 whitelist 过滤;默认建议 whitelist

    {Public Domain, CC0, CC BY 4.0, CC BY-SA 4.0, MIT, Apache-2.0, BSD*, CERN-OHL*}
    

6. Schema 映射

对齐 schemas/project.schema.json(跨源统一 schema

本项目 schema 字段 oshwhub 来源
source 常量 "oshwhub"
source_url https://oshwhub.com/<path>
project_id uuid32 hex
title 详情页 <title> 去后缀,或列表 name
description_short 列表 introduction
description_path "description.md"(本地文件)
author.username owner.username
author.display_name owner.nickname
author.user_id owner.uuid
license SSR HTML 嵌入 JSON 的 license 字段;缺省 "unknown"
tags 列表 tags
created_at, updated_at 列表同名字段
published_at oshwhub_publish_at
crawled_at 运行时 datetime.now(timezone.utc)
metrics.{likes,stars,forks,views,watch,comments} count.{like,star,fork,views,watch} + comments_count
cover.url / cover.path thumb / 本地 cover.*
files[].{name,url,size,md5,ext,mime,original_id} attachments[] 逐字段映射
files[].{path,sha256} 下载后写入
raw_fields.{path,grade,origin,public,publish} 保留源站原始字段

7. 速率与礼貌

当前配置(crawlers/oshwhub/crawler.py

动作 频率
列表 API 页间隔 2 sSLEEP_BETWEENQPS 0.5
详情 HTML 同上,每次 ~500 KB
附件下载 (image.lceda.cn) 每个文件后 2 s sleep

UA 声明为 FacereDataset/0.1 (+https://git.deepknow.site/Facere/FacereDataset)不伪装浏览器

实测无 rate-limit 触发。放量时建议并发 ≤ 3遇 429/5xx 指数退避,连续失败 ≥ 5 次停爬人工介入。


8. 目录输出约定

每个项目落盘到:

data/raw/oshwhub/<uuid>/
├── metadata.json       # 符合 schemas/project.schema.json
├── description.md      # 标题 + 简介 + 作者/许可证/发布时间
├── cover.{jpg,png,jpeg} # 封面(普通 git
├── _urls.json          # 所有原始 URL 清单(重下用)
└── files/              # 原始附件Git LFS见 .gitattributes
    ├── xxx.pdf
    ├── xxx.zip
    └── ...

9. 已知风险与未解决

# 风险 / 问题 影响 当前策略 / 缓解
R1 站点加反爬UA 指纹 / 验证码 / IP 限) 放量中断 自律 QPS ≤ 0.5;若触发切换到 lightpanda 或真 Chrome + 降速
R2 license: "unknown" 或非标准字符串 下游合规风险 严格 whitelist 过滤;oshwhub_license_normalize 待建
R3 单项目附件 > 100 MB LFS 存储激增 目前 p90=54 MB 可接受;大于阈值记录 URL 不下载的开关待加 (--max-file-size)
R4 EasyEDA 源 JSON 需登录 账号被封 → 工程源获取中断 Phase 1.6 登录爬QPS ≤ 0.2,账号隔离在云服务器 ~/.secrets/,必要时多号轮询
R5 长描述 HTML 格式保真 文本语料噪声 当前只存简介;长文本提取(含图片/表格)留待 Phase 5 清洗
R6 grade 字段含义未官方公开 质量筛选判据模糊 经验grade=4 是精品徽章;其它档位抽样判据后续补
R7 增量更新策略 重复抓取浪费 updated_at 对比 + LFS prune 策略未实现

附录 A — 一次性重跑

# 规模估算(无下载)
uv run python scripts/estimate_size.py --pages 3 --page-size 30 --sort hot

# 列表 API 探测
curl -s "https://oshwhub.com/api/project?page=1&pageSize=1" | python3 -m json.tool

# 某项目详情
curl -s "https://oshwhub.com/CYIIOT/ST_LINK-V2_1" -o /tmp/detail.html

# MVP 爬取 10 个高质量
uv run python -m crawlers.oshwhub --top 10 --min-likes 50 --min-grade 4

# 指定 UUID 列表爬
uv run python -m crawlers.oshwhub --uuids aaa,bbb,ccc --out data/raw/oshwhub

附录 B — 变更历史

日期 变更
2026-04-23 首版API 探索、SSR 解析方案、fs-web-stream 排查、12 493 总数验证、90 项目采样(体积 / 类型 / license 分布)合并成本文