From bf2370f83b6ee20649d8155bf5da4be947fc7460 Mon Sep 17 00:00:00 2001 From: Zhang Jiahao Date: Thu, 23 Apr 2026 18:58:10 +0800 Subject: [PATCH] Initial skeleton for FacereDataset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: - Facere 需要一个统一的开源硬件设计数据源,用于训练专有模型与 构建检索型知识库。仓库先立骨架,把合规红线、数据 schema 要求、 爬虫规约写在 CLAUDE.md 里,避免后续实现时各站点爬虫写法发散。 - plan.md 用阶段化路线图明确"先广度后深度、先合规后规模"的策略, 让放量前必须经过 Charles 对齐一次,降低存储与法律风险。 Contents: - README.md: 项目简介、数据源表、仓库结构、合规声明 - CLAUDE.md: 项目级 Claude 指令(工作流 / 爬虫规约 / 合规红线) - plan.md: Phase 0-6 分阶段计划 + 风险与未决项 - log.md: 首条日志(调研 + 初始化记录) - .gitignore: 排除 data/{raw,processed,state} 内容,保留目录占位 - 目录骨架: crawlers/ schemas/ scripts/ data/ docs/sources/ Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 39 ++++++++++++ CLAUDE.md | 56 +++++++++++++++++ README.md | 68 ++++++++++++++++++++ crawlers/.gitkeep | 0 data/processed/.gitkeep | 0 data/raw/.gitkeep | 0 data/state/.gitkeep | 0 docs/.gitkeep | 0 docs/sources/.gitkeep | 0 log.md | 34 ++++++++++ plan.md | 135 ++++++++++++++++++++++++++++++++++++++++ schemas/.gitkeep | 0 scripts/.gitkeep | 0 13 files changed, 332 insertions(+) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 crawlers/.gitkeep create mode 100644 data/processed/.gitkeep create mode 100644 data/raw/.gitkeep create mode 100644 data/state/.gitkeep create mode 100644 docs/.gitkeep create mode 100644 docs/sources/.gitkeep create mode 100644 log.md create mode 100644 plan.md create mode 100644 schemas/.gitkeep create mode 100644 scripts/.gitkeep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..19592fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Data outputs (大文件不入库,走 LFS 或外部存储) +# 忽略目录内容,保留目录本身(靠 .gitkeep 占位) +data/raw/* +data/processed/* +data/state/* +!data/raw/.gitkeep +!data/processed/.gitkeep +!data/state/.gitkeep + +# Python +__pycache__/ +*.py[cod] +*.egg-info/ +.pytest_cache/ +.ruff_cache/ +.mypy_cache/ +.venv/ +venv/ +.env +.env.* +!.env.example + +# uv +uv.lock + +# Node (if we add JS helpers) +node_modules/ + +# Editor / OS +.vscode/ +.idea/ +.DS_Store +Thumbs.db +*.swp + +# Local scratch +/tmp/ +/scratch/ +*.log diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..35ad4bb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,56 @@ +# CLAUDE.md — FacereDataset + +项目级 Claude Code 指令。与 `~/.claude/CLAUDE.md` 全局指令合并使用,本文件覆盖冲突项。 + +## 项目性质 + +数据集仓库。产出代码 + 元数据 + (通过 LFS 或外链引用的)原始资产。不要把几百 MB 的 Gerber / STEP 直接塞进 git。 + +## 核心工作流 + +1. **每次重要动作结束后**:追加一条到 `log.md`(时间倒序,顶部最新),格式: + ``` + ## YYYY-MM-DD HH:MM <一句话概括> + - 做了什么 + - 为什么(如果非显然) + - 下一步建议 + ``` +2. **计划有调整时**:更新 `plan.md`,不要新建 `plan_v2.md`。 +3. **新增爬虫**:放到 `crawlers//`,至少包含 `__init__.py` 入口、`README.md`(目标站点调研),遵循 `schemas/project.schema.json`。 +4. **数据输出位置**:`data/raw///` 存原始响应(JSON/HTML),`data/processed//` 存清洗后的 jsonl。两者都在 `.gitignore` 里,不入库。 + +## 爬虫规约 + +- **速率**:默认 QPS ≤ 1/site,并发 ≤ 3。可配置但不得默认贪婪。 +- **缓存**:所有 HTTP 响应落盘(`data/raw/...` + `requests-cache` 或 httpx + diskcache),重跑不要重新打目标站。 +- **UA**:声明为 `FacereDataset/ (+; contact:)`,不要伪造浏览器。**例外**:目标站主动封标识 UA、且内容属公开静态资源时,允许切 lightpanda/web-access 真浏览器模式,并在 commit message 说明原因。 +- **robots.txt**:每个爬虫 **必须** 先查 `robots.txt`;命中 Disallow 的路径直接跳过,不要"绕过"。 +- **登录态**:本项目**不**抓需要登录的内容。 +- **失败重试**:指数退避 + jitter;连续 5xx / 429 超过阈值要停爬、提醒人介入,不要傻重试。 +- **断点续跑**:state 记到 `data/state/.json`(游标、已处理 ID 集合)。 + +## 数据 schema + +统一以 `schemas/project.schema.json` 为准。每条项目记录至少包含: +`source`, `source_url`, `project_id`, `title`, `description`, `author`, `license`, `created_at`, `updated_at`, `crawled_at`, `tags`, `files[]`(每个文件 `type` / `path` / `size` / `sha256`)。 + +## 合规红线 + +- 不抓登录墙后的内容。 +- 不绕过付费墙、不破解 DRM。 +- 遇到站点明确声明"禁止抓取/训练"的内容,跳过并记录到 `data/state/_excluded.jsonl`。 +- 每条记录**必须**保留 `license` 字段;无法判定的标 `license: "unknown"` 并在下游过滤时默认剔除。 + +## 约定(项目内部) + +- 语言:代码/注释/commit 英文;文档(README / plan / log)中文。 +- Python:3.11+,`uv` 管理依赖,`ruff` 做 lint/format,`pytest` 测试。 +- 不要为"以防万一"添加抽象或配置项;多爬虫共享需求再抽共用代码。 +- commit message 说清楚 **why**,尤其是涉及数据过滤、许可证判定逻辑的改动。 + +## Claude 行为提醒 + +- 启动任何爬虫前,先跑 dry-run(`--limit 1 --no-write`),确认 schema 和速率正确。 +- 一次只推进 `plan.md` 的一个阶段,推进后更新 `log.md`。 +- 涉及数据删除(`rm` `data/`)必须先跟 Charles 确认。 +- 新发现的反爬/法律坑录入 `docs/pitfalls.md`,不要只放在 log。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d3869b --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# FacereDataset + +为 **Facere** 专有模型训练与硬件设计知识库提供数据支撑的开源硬件设计数据集。 + +## 目标 + +采集、清洗、结构化互联网公开可用的硬件设计资产(原理图、PCB、BOM、Gerber、3D 模型、固件、文档),输出: + +1. **训练数据集**:可直接喂给 LLM / 多模态模型做预训练、SFT、RAG 的结构化语料。 +2. **检索型知识库**:按元器件、拓扑、应用领域可查的设计参考库。 +3. **派生产物**:元件封装库、常见子电路模板、BOM 成本曲线等。 + +## 数据来源(第一批) + +| 站点 | URL | 覆盖 | 许可 | 抓取复杂度 | +|------|-----|------|------|-----------| +| 立创开源平台 | oshwhub.com | 国内 PCB/EDA 设计 ~百万量级 | 多为 CC-BY-SA / 作者自定 | 中(SPA,需 API 逆向) | +| 嘉立创 EDA 样例 | lceda.cn/example | 官方示例 | 开放 | 低 | +| Hackaday.io | hackaday.io | 项目叙事 + 文件 | 作者自定 | 中 | +| GitHub | github.com | KiCad/EasyEDA repo | 各 repo 自定 | 低(gh API) | +| CERN OHR | ohwr.org | 高质量工业级 | CERN-OHL | 低 | +| Wikifactory | wikifactory.com | 社区项目 | 作者自定 | 中 | + +详细爬取计划见 [`plan.md`](./plan.md)。 + +## 仓库结构 + +``` +FacereDataset/ +├── README.md 项目简介(本文件) +├── CLAUDE.md Claude Code 项目级指令 +├── plan.md 分阶段爬取与处理计划 +├── log.md 执行日志(时间倒序) +├── crawlers/ 各站点爬虫(一站一子包) +├── schemas/ 统一数据 schema(project.schema.json) +├── scripts/ 去重、格式转换、完整性校验工具 +├── data/ 数据产出(raw/ processed/,大文件走 LFS 或外部存储) +└── docs/ 设计笔记、法律合规、数据字典 +``` + +## 合法与伦理 + +- 只抓取**公开可访问**、标注为开源或明确允许再分发的内容。 +- 遵守目标站点的 `robots.txt` 与 ToS;登录才能访问的内容不在本项目范围内。 +- 每条记录保留 `source_url`、`author`、`license`、`crawled_at` 作溯源。 +- 商业使用前按许可证逐条核对(CC-BY 要求署名,CC-BY-SA 要求同许可分享,等)。 + +## 快速开始 + +```bash +# 克隆 +git clone https://git.deepknow.site/Facere/FacereDataset.git +cd FacereDataset + +# 安装(Python 3.11+,uv) +uv sync + +# 运行某个爬虫 +uv run python -m crawlers.oshwhub --limit 10 +``` + +> 当前处于骨架初始化阶段,爬虫尚未实现。见 `plan.md` Phase 1。 + +## 维护 + +- 主要维护者:Charles(`git.deepknow.site/Knowit`) +- 远端:`git.deepknow.site/Facere/FacereDataset` +- 问题追踪:Gitea Issues diff --git a/crawlers/.gitkeep b/crawlers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/processed/.gitkeep b/data/processed/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/raw/.gitkeep b/data/raw/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/state/.gitkeep b/data/state/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/.gitkeep b/docs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/sources/.gitkeep b/docs/sources/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/log.md b/log.md new file mode 100644 index 0000000..68eddd9 --- /dev/null +++ b/log.md @@ -0,0 +1,34 @@ +# FacereDataset 执行日志 + +时间倒序,最新在顶部。 + +--- + +## 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/`(示例 `f0652fd2ae3e40b8a0ecc8dc773e3512`) + - 图片 CDN:`image.lceda.cn/oshwhub/pullImage/...` + - 文件下载:`fs-web-stream.jlc.com/fs-web-stream/file-operation/download/` + - 页面是 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` + +**下一步建议给 Charles**: +1. 拍板存储方案(本地盘 / Gitea LFS / 外部 OSS)—— 影响 Phase 1.4 放量时机 +2. 目标规模(1 万 / 10 万 / 全量) +3. 决定是否保留二进制附件或只存 URL +4. 完成上述 3 项后启动 Phase 1.1(用 `chrome-devtools` MCP 录 oshwhub 的 network trace 定位真实 API) diff --git a/plan.md b/plan.md new file mode 100644 index 0000000..fefc155 --- /dev/null +++ b/plan.md @@ -0,0 +1,135 @@ +# FacereDataset 爬取与建设计划 + +**维护**:Charles +**最近更新**:2026-04-23 +**状态**:Phase 0 已完成(仓库骨架),Phase 1 待启动 + +--- + +## 总体策略 + +**先广度后深度,先合规后规模。** + +1. 每个数据源先做一份 "可行性调研"(一页纸,放 `docs/sources/.md`),明确:访问形式、速率限制、许可证分布、ToS 摘要、数据字段覆盖。 +2. 每个站点实现一个最小 MVP 爬虫,**单项目跑通** → 然后才全量化。 +3. 全量化之前先跟 Charles 对齐抽样结果与存储开销。 +4. 所有站点输出统一到 `schemas/project.schema.json` 定义的结构,不要让下游消费者去适配 N 种 schema。 + +--- + +## Phase 0 — 仓库骨架 ✅ + +- [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] 初始提交并推送 + +--- + +## Phase 1 — 立创开源平台(oshwhub.com)MVP + +**目标**:跑通 10 个项目的完整抓取,验证 schema。 +**预计工期**:2-3 天(人+Claude 协作) + +### 1.1 调研(0.5 天) + +- [ ] 确认 API 入口:Next.js SPA,首页 800KB HTML 里内联了首屏 props,但翻页/详情靠 `/_next/data//...json` 或 XHR。需要: + - 打开浏览器 DevTools,录一段 explore → 详情 → 下载的 network trace,提取 API endpoints(推荐 `chrome-devtools` MCP) + - 核对 `sitemap.xml` 作为项目 URL 源(已确认存在) +- [ ] 许可证字段位置:详情页有"开源协议"显示,确认对应 JSON key +- [ ] 确认 sitemap 完整性:是否覆盖全部公开项目;若否,fallback 用 `/explore?sort=hot&page=N` + +### 1.2 爬虫 MVP(1 天) + +`crawlers/oshwhub/`: + +- [ ] `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 指数退避 + +### 1.3 验收(0.5 天) + +- [ ] 跑 `--limit 10` 成功,10 条 jsonl 通过 schema 校验(`scripts/validate.py`) +- [ ] 抽查 3 条人工确认字段正确 +- [ ] 产出 `docs/sources/oshwhub.md` 调研笔记 + +### 1.4 放量(视情况) + +- [ ] 估算全量规模(项目数 × 平均附件大小) +- [ ] 跟 Charles 对齐存储方案(LFS vs S3 vs 单机盘) +- [ ] 分批跑(每批 1-5 万项目),产出进度报告 + +--- + +## Phase 2 — GitHub 开源硬件 repo + +**目标**:抓 KiCad / EasyEDA / Eagle 格式的公开 repo。 + +- [ ] 用 GitHub Code Search API 查 `extension:kicad_pcb` / `extension:sch` / `filename:*.epro` 等 +- [ ] 过滤 star ≥ N(降噪,可调) +- [ ] 抓 repo 元数据 + 文件树 + 关键文件,**不 clone 全仓**(省带宽) +- [ ] License 从 repo `LICENSE` 文件 + GitHub API `license` 字段双取 +- [ ] MCP:优先 `mcp__github__*` 工具;大规模批量可切 `gh api` + `gitingest` + +预计工期:3-5 天。 + +--- + +## Phase 3 — Hackaday.io + +- [ ] 探测是否有公开 API(`/api/v1/` 曾经存在,需 key) +- [ ] 若无 API:解析 explore 列表 + project/log 页面 +- [ ] 重点抓项目叙事(README / build log)——这是 LLM 语料的高价值部分 + +预计工期:3 天。 + +--- + +## Phase 4 — 长尾站点 + +并列小项目,每个 0.5-1 天: + +- [ ] CERN OHR(`ohwr.org`)—— 高质量、CERN-OHL 许可清晰 +- [ ] Wikifactory +- [ ] Open Hardware Park +- [ ] Tindie(仅商品元数据,文件多半不公开) +- [ ] Instructables 硬件类目(文本叙事为主) + +--- + +## Phase 5 — 数据清洗与派生 + +- [ ] 去重:`sha256(files)` + `(title, author)` 模糊匹配 +- [ ] 质量打分:字段完整度 + 文件大小合理性 + license 有效性 +- [ ] 派生数据集: + - `components.jsonl`:从 BOM 汇总常见元件 → 成本曲线 + - `subcircuits.jsonl`:常见子电路模板(电源、USB、MCU 最小系统) + - `narratives.jsonl`:项目叙事文本语料(给 LLM 预训练) +- [ ] 生成 README 级统计:项目总数、许可证分布、站点覆盖 + +--- + +## Phase 6 — 持续运营 + +- [ ] 增量爬取 cron:每站点每周扫一次新增/更新 +- [ ] 数据发布:版本化 snapshot(v0.1, v0.2, ...),Release tag 到 Gitea +- [ ] 反馈回路:模型训练团队发现脏数据 → issue → 过滤规则下沉到 `scripts/` + +--- + +## 风险与未决项 + +| 风险 | 影响 | 缓解 | +|-----|-----|-----| +| oshwhub 反爬加强 | 卡住 Phase 1 | 切 lightpanda/真 Chrome;降速;部分内容弃 | +| 许可证字段缺失 / 模糊 | 下游训练合规风险 | 默认剔除 `license: unknown`;建 whitelist | +| 单个项目附件过大(>100MB) | 存储爆炸 | Phase 1 调研时统计分布;大文件走外部 OSS,记录 URL 不本地化 | +| GitHub API rate limit | Phase 2 慢 | 使用已登录 `gh` token;必要时换 fine-grained PAT | +| 站点改版 | 爬虫失效 | 爬虫带 schema 自检,HTML 结构变化时告警 | + +**未决**(需要 Charles 定): +- 数据存储方案:本地盘(够吗?)、Gitea LFS、或外挂对象存储? +- 是否要保留图片/Gerber/STEP 的二进制,还是只存 URL? +- 目标规模:第一版想要 1 万 / 10 万 / 全量? diff --git a/schemas/.gitkeep b/schemas/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/scripts/.gitkeep b/scripts/.gitkeep new file mode 100644 index 0000000..e69de29