Why: - schema 必须能自动校验,否则后续放量无法防腐。现在 scripts/validate.py 对全部 metadata.json 做两层检查(schema + 本地文件 sha256),跑一次 即可对全量数据签收;10/10 项目已通过。 - docs/sources/oshwhub.md 之前把 fs-web-stream.jlc.com 标为"工程源待查", 排查后确认那些 URL 全部是嘉立创服务侧栏/推广图标,与项目无关。 image.lceda.cn/attachments/ 是项目附件的唯一入口,现在调研文档闭合。 What: - scripts/validate.py: jsonschema 校验 + optional --check-files 核 sha256 - pyproject.toml: 加 jsonschema>=4.26 依赖 - docs/sources/oshwhub.md: fs-web-stream 归类为推广资源(已排除),附 context 证据 - log.md: 本次会话记录 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
98 lines
3.9 KiB
Markdown
98 lines
3.9 KiB
Markdown
# oshwhub.com 数据源调研
|
||
|
||
**平台**:立创开源硬件平台(嘉立创 EDA / 深圳创电优选科技有限公司)
|
||
**URL**:https://oshwhub.com
|
||
**调研日期**:2026-04-23
|
||
|
||
## 站点架构
|
||
|
||
- Next.js App Router SPA;详情页 `/detail/<uuid>` 和 `/<user>/<slug>` 均 SSR(HTML 内含完整元数据 + attachments 数组)
|
||
- axios baseURL 为 `https://oshwhub.com`(见 `/_next/static/chunks/8661-*.js`)
|
||
- 首页 / explore 列表数据靠客户端 fetch 渲染(首屏 HTML 里没有卡片 DOM)
|
||
|
||
## robots.txt
|
||
|
||
```
|
||
User-agent: *
|
||
Disallow: /posts
|
||
Sitemap: https://oshwhub.com/sitemap.xml
|
||
```
|
||
|
||
详情页、explore、API 均允许抓取。
|
||
|
||
## 可用 API(无需鉴权)
|
||
|
||
### 项目列表
|
||
`GET https://oshwhub.com/api/project?page=N&pageSize=M&sort=hot`
|
||
|
||
- `sort`:`hot`(默认,按热度)/`like`/`new` 等
|
||
- `pageSize`:最大 50 可用,试过 100 返回空
|
||
- 返回:`{success, code, result:{page, pageSize, total, totalPage, lists:[...]}}`
|
||
- total ≈ 12493(2026-04 快照)
|
||
|
||
每条 list item 字段:
|
||
- `uuid`, `name`, `introduction`, `path`(= `<username>/<slug>`)
|
||
- `owner`:`{uuid, username, nickname, avatar, team}`
|
||
- `count`:`{fork, star, like, views, watch}`
|
||
- `grade`(1-4,4 是精品徽章)
|
||
- `thumb`(封面 URL,`image.lceda.cn` 或 `//image.lceda.cn` 前缀)
|
||
- `created_at`, `updated_at`, `oshwhub_publish_at`
|
||
- `tags`, `public`, `publish`, `comments_count`
|
||
|
||
### 项目详情(HTML 解析)
|
||
`GET https://oshwhub.com/<path>` 或 `/detail/<uuid>`
|
||
|
||
HTML 内嵌 escaped JSON,关键字段:
|
||
- `\"license\":\"GPL 3.0\"` 等(许可证)
|
||
- `\"creator\":{\"uuid\":\"...\"}`
|
||
- `\"attachments\":[{ name, src, mime, ext, size, md5, download_count, uuid }, ...]`
|
||
- `<title>` 含项目名;`<meta name="description">` 含 introduction
|
||
|
||
### 文件下载
|
||
- **附件** (`attachments[].src`):`https://image.lceda.cn{src}`
|
||
- 例:`/attachments/2020/7/mRn5hQZRhmx5r4usGxFmy8BXsCIHw5QoAT5HaLGC.pdf`
|
||
- 已验证 HTTP 200,无鉴权
|
||
- 覆盖 PDF / ZIP / MP4 / CSV / BIN 等(用户自传全类型)
|
||
- **这是项目用户文件的唯一入口**(已排查确认)
|
||
|
||
### 排查过不是项目源的路径
|
||
- `fs-web-stream.jlc.com/fs-web-stream/file-operation/download/<snowflake-id>`
|
||
- 详情页 HTML 里出现过 13 个,context 均为站点侧栏/推广图标
|
||
- 例:嘉立创 3D 打印 icon、开源硬件平台 badge、EDA 扩展广场 banner
|
||
- **与项目本身无关**,不抓
|
||
|
||
### 未找到 / 留作后续
|
||
- EasyEDA 工程源 JSON(schematic/PCB 的真正源):`u.lceda.cn/api/projects` 返回 401 "尚未登录",需要登录态
|
||
- 项目详情 JSON API:`/api/project/<uuid>` 返回 `{"code":104001,"success":false}`(试过 GET/POST/路径形式均失败,疑似此端点需 session)
|
||
- 当前通过 SSR HTML 解析获取详情,字段够用
|
||
|
||
## 已知字段与 schema 映射
|
||
|
||
| 本项目 schema 字段 | oshwhub 来源 |
|
||
|-----|-----|
|
||
| `source` | 常量 `"oshwhub"` |
|
||
| `source_url` | `https://oshwhub.com/<path>` |
|
||
| `project_id` | `uuid` |
|
||
| `title` | `name` |
|
||
| `description` | HTML `<meta description>` + 长描述(HTML 正文截取) |
|
||
| `author` | `owner.nickname` / `owner.username` |
|
||
| `license` | HTML 嵌入 JSON 的 `license` 字段 |
|
||
| `created_at` / `updated_at` | 列表 API 同名字段 |
|
||
| `crawled_at` | 运行时写入 |
|
||
| `tags` | 列表 API `tags` |
|
||
| `files[]` | `attachments[]` 映射 |
|
||
| `metrics` | `count.{like,star,fork,views}` + `grade` |
|
||
|
||
## 速率与礼貌
|
||
|
||
- 列表 API:空载实测 < 300ms,无限流
|
||
- 详情页 HTML:~500KB/个,建议 QPS ≤ 0.5
|
||
- 附件:CDN `image.lceda.cn`,无需限流但建议 1s 间隔
|
||
|
||
## 陷阱 / 待确认
|
||
|
||
1. `fs-web-stream.jlc.com` 下载是否需 referer / cookie,未测
|
||
2. 长描述(含图片、表格)的 HTML 提取保真度,可能需要保留原 HTML
|
||
3. `license` 字段取值集合未枚举完(已见:`GPL 3.0` / `CC-BY-SA`...需全量跑后统计)
|
||
4. `grade=4` 大概率是精品徽章但文档未说明具体判据
|