Phase 1 MVP: crawl 10 high-quality oshwhub projects into LFS

Why:
- Charles 指定:先爬 10 个高质量项目存 Gitea LFS,一个项目一个文件夹,
  保留原文件和 URL。先以小批量验证 schema + LFS 流水线,放量前再拍板
  存储规模。

What:
- crawlers/oshwhub: 列表 API (`/api/project?sort=hot`) + SSR HTML 解析,
  一次性产出 metadata / description / cover / files / _urls
- schemas/project.schema.json: 跨源统一 schema
- docs/sources/oshwhub.md: API 入口 / 字段映射 / 陷阱调研
- pyproject.toml: httpx[http2] 单依赖
- .gitattributes: data/raw/**/files/** 一律走 LFS(规则写窄,避免误伤 schemas/*.json 等)
- .gitignore: 移除 data/raw/* 排除(改走 LFS 入库)

10 个项目覆盖:调试器 / 加热台 / 盖革计数器 / 数控电源 / 焊台 /
智能手表 / USB 测电流 / ZVS 感应加热 / AI 开发板 / 红外热成像。
共 52 附件 ≈ 524 MB 入 LFS,筛选判据 grade=4 & likes>=100 & 多样性。

Known gaps(见 plan.md § Phase 1.4):
- EasyEDA 源 JSON 需登录 (u.lceda.cn),v0.1 跳过
- fs-web-stream.jlc.com 的工程源下载未测
- scripts/validate.py 自动 schema 校验未实现

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Zhang Jiahao
2026-04-23 19:34:09 +08:00
parent bf2370f83b
commit 5ffa10f256
103 changed files with 2279 additions and 28 deletions

49
plan.md
View File

@@ -21,45 +21,46 @@
- [x] `README.md` / `CLAUDE.md` / `plan.md` / `log.md`
- [x] 目录骨架 `crawlers/ schemas/ scripts/ data/ docs/`
- [x] `.gitignore`(排除 `data/raw` `data/processed` `data/state` `venv` `__pycache__`
- [x] `.gitignore`(排除 derivative 目录)/ `.gitattributes`LFS 规则
- [x] 初始提交并推送
---
## Phase 1 — 立创开源平台oshwhub.comMVP
## Phase 1 — 立创开源平台oshwhub.comMVP ✅ 首批完成
**目标**:跑通 10 个项目的完整抓取,验证 schema。
**预计工期**2-3 天(人+Claude 协作)
**实际**10/10 成功52 附件524 MB 入 LFS。
### 1.1 调研0.5 天)
### 1.1 调研
- [ ] 确认 API 入口Next.js SPA首页 800KB HTML 里内联了首屏 props但翻页/详情靠 `/_next/data/<buildId>/...json` 或 XHR。需要
- 打开浏览器 DevTools录一段 explore → 详情 → 下载的 network trace提取 API endpoints推荐 `chrome-devtools` MCP
- 核对 `sitemap.xml` 作为项目 URL 源(已确认存在)
- [ ] 许可证字段位置:详情页有"开源协议"显示,确认对应 JSON key
- [ ] 确认 sitemap 完整性是否覆盖全部公开项目若否fallback 用 `/explore?sort=hot&page=N`
- [x] 列表 API `/api/project?page=N&pageSize=M&sort=hot`(无鉴权)
- [x] 详情页 SSR HTML 嵌入 escaped JSON含 attachments 数组与 license
- [x] 附件 CDN `image.lceda.cn/{src}` 直连
- [x] `docs/sources/oshwhub.md` 调研笔记
### 1.2 爬虫 MVP1 天)
### 1.2 爬虫 MVP
`crawlers/oshwhub/`
`crawlers/oshwhub/crawler.py`
- [ ] `discover.py` — 从 sitemap + explore 列表产出项目 ID stream去重、断点续
- [ ] `fetch.py` — 单项目抓取:详情 JSON、预览图、可下载文件原理图 JSON / 工程压缩包)
- [ ] `normalize.py` — 映射到统一 schema`data/processed/oshwhub/projects.jsonl`
- [ ] `__main__.py` — CLI`--limit N --since DATE --resume`
- [ ] 速率:默认 QPS 0.5,遇 429/5xx 指数退避
- [x] 列表分页 + 质量打分排序
- [x] HTML 解析title / description / license / attachments
- [x] 每项目目录metadata / description / cover / files / _urls
- [x] QPS ≤ 0.5UA 真实声明
### 1.3 验收0.5 天)
### 1.3 验收
- [ ] `--limit 10` 成功10 条 jsonl 通过 schema 校验(`scripts/validate.py`
- [ ] 抽查 3 条人工确认字段正确
- [ ] 产出 `docs/sources/oshwhub.md` 调研笔记
- [x] 10/10 成功,产出符合 `schemas/project.schema.json`
- [ ] **待 Charles**:随机抽查 2-3 条对照原站
- [ ] `scripts/validate.py` 自动 schema 校验(未写,后续补)
### 1.4 放量(视情况
### 1.4 放量(待决策
- [ ] 估算全量规模(项目数 × 平均附件大小)
- [ ] 跟 Charles 对齐存储方案LFS vs S3 vs 单机盘
- [ ] 分批跑(每批 1-5 万项目),产出进度报告
- [ ] Charles 定目标规模50 / 500 / 5000 / 全量 12493
- [ ] 估算存储52 附件 / 10 项目 ≈ 52MB/项目 → 全量约 **650GB**Gitea LFS 需评估
- [ ] 未解决:
- `fs-web-stream.jlc.com` 工程源下载路径(未测)
- `u.lceda.cn` EasyEDA 工程 JSON需登录v0.1 跳过)
- 增量更新:`updated_at` 变动检测 + LFS prune 策略
---