Files
FacereDataset/docs/plans/oshwhub_batch200.md
Knowit 7cb35020f4 plan: batch-200 expansion (100 Pro + 100 Std)
Doubles down on what worked in batch-50:
  - dev1 (Guangzhou) is primary execution host
  - Owner cap=2 for diversity
  - --max-source-mb 200 to defend against X86-class outliers
  - Pro 2.x deprecated-board fix is already in (commit c3cac97)
  - SSH transport for dev1 -> gitea (commit 8220c99)

Candidate pool:
  200 picks from A-tier (grade>=3 & like>=10) minus already-crawled 65
  Remaining A-tier corpus is 2,741 (Pro 1326 + Std 1415)
  173 unique authors, like median 258, grade dist 4:118 / 3:82

Estimated walltime ~25-35 min on dev1 for Step 1-4 (no attachments).
LFS increment ~2.5 GB (source only) or +10 GB if Step 5 attachments
included. Either way well within Gitea's 200 GB migration threshold.

Step 5 (attachment download) deferred — not on the critical path for
EPRO2/Std → KiCad work, can revisit when license-filtered Forge
projection demands it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 02:29:53 +08:00

186 lines
7.7 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.
# oshwhub 扩抓批 200执行计划
**创建**2026-04-29
**承接**`docs/plans/oshwhub_batch50.md`(已 100% 完结)
**目标**:从 65 项扩到 265 项 — 验证流水线在中等规模的稳定性,开始覆盖 A 档第二梯队
**候选清单**`data/state/oshwhub_batch200_candidates.jsonl`200 行)
**主执行机**dev1广州~30× 网络优势已实测)
---
## 1. batch-50 经验回放(影响这一批的设计)
| 教训 | 这一批的对策 |
|---|---|
| dev1 Guangzhou 网络是关键加速器 | 全部步骤都在 dev1 跑SG 这边只是同步消费 |
| Pro 2.x 占高质量 Pro 池 80% | Pro 2.x parser 必须稳deprecated-board 已修 |
| `git push` 单次 70 MB 在 dev1 → gitea 链路 6.5% 丢包 → 360 KB/s | dev1 origin 已切 SSH 协议commit `8220c99`),后续 push 流畅 |
| `--max-source-mb 200` 没触发25 Pro 最大才 9 MB| 保留 cap 防 X86-class outlier但预期触发率极低 |
| `git push 2>&1 \| tail -5` 永远 exit 0 吞掉错误 | 启用 `set -o pipefail` 或检查 PIPESTATUS |
| Pro 2.x boards[] 可能含废弃 sch/pcb 返 401 | 已修:`ticket.schematics`/`pcbs` 求交集commit `c3cac97`|
| 详情 HTML 抓取是 server-render bound~50ms / 项)| 不优化;本批 200 项 ~10s 即可 |
---
## 2. 候选池筛选标准(与 batch-50 一致)
数据源:`data/state/oshwhub_listing_full.jsonl`33,695 项全量索引)
**硬过滤**
- `grade >= 3 AND like >= 10`A 档)
- `uuid` 不在已抓 65 项内(剩余 A 档 = 2,741 项 Pro 1326 + Std 1415
**排序**`like*3 + star + fork*2 + views/100 + comments*2 + grade*50`
**多样性约束**
- 单作者全局上限 2
- Pro / Std 100:100 均衡(同 batch-50 思路)
---
## 3. 选出的 200 项概况
| 维度 | 值 |
|---|---|
| 总数 | 200100 Pro + 100 Std |
| 唯一作者 | 173max 单作者 2 项) |
| like 区间 | min=22 / median=258 / max=624 |
| grade 分布 | 4: 118 项, 3: 82 项 |
> like 中位数 258 比 batch-50 的 554 低——因为 batch-50 已经吃掉了 A 档头部。本批进入 A 档第二梯队,整体仍合格。
完整名单见 `data/state/oshwhub_batch200_candidates.jsonl`
---
## 4. 执行步骤
> 全部在 dev1 跑。SG 端只 `git pull` 消费成果。
### Step 0 — 候选池冻结 ✅
`oshwhub_batch200_candidates.jsonl` 已生成。
### Step 1 — 详情页扫 license~3 min @ concurrency=5
```bash
ssh dev1 'export PATH=$HOME/.local/bin:$PATH && \
cd ~/repo/FacereDataset && \
PYTHONUNBUFFERED=1 uv run python -u -m crawlers.oshwhub \
--from-jsonl data/state/oshwhub_batch200_candidates.jsonl \
--no-files --no-cover --concurrency 5 \
--out data/raw/oshwhub'
```
预期200 项 / ~3-5 分钟dev1 详情页 p90=73ms × 200/5 并发 ≈ 3s 网络 + server render 时间 ≈ 几分钟)。
### Step 2 — license 分布盘点(无过滤入库)
```bash
ssh dev1 'cd ~/repo/FacereDataset && uv run python - <<EOF
import json, glob, collections
target = {json.loads(ln)["uuid"] for ln in open("data/state/oshwhub_batch200_candidates.jsonl")}
licenses = collections.Counter()
for p in glob.glob("data/raw/oshwhub/*/metadata.json"):
m = json.load(open(p))
if m.get("project_id") in target:
licenses[m.get("license") or "<unknown>"] += 1
for lic, n in licenses.most_common():
print(f" {n:>4} {lic}")
EOF'
```
按 batch-50 数据外推:~64% GPL 3.0、~16% Forge-friendly 自由、~16% NC variants。
### Step 3 — Pro 100 项 backfill source~10-15 min
```bash
ssh dev1 'export PATH=$HOME/.local/bin:$PATH && \
cd ~/repo/FacereDataset && \
PRO_UUIDS=$(jq -r "select(.origin==\"pro\") | .uuid" \
data/state/oshwhub_batch200_candidates.jsonl | paste -sd,) && \
PYTHONUNBUFFERED=1 uv run python -u -m crawlers.oshwhub \
--backfill-pro-source \
--uuids "$PRO_UUIDS" \
--max-source-mb 200'
```
预期分布(按 batch-50 的 Pro 比例外推):
- Pro 2.x legacy ~80 项chain 平均 < 30每项 ~30s → ~40 分钟……
> 等等得拆估算dev1 端 Pro chain 是 0.5s sleep × N + CDN 0.2s × M。粗算单项 average = 0.5×5 + 0.2×30 = 8.5s。100 项串行 = ~14 min。
> 如果想再快可以加 backfill 路径的 concurrency目前没加是个小改动。先不优化看实测。
### Step 4 — Std 100 项 backfill source~5-10 min
```bash
STD_UUIDS=$(jq -r 'select(.origin=="std") | .uuid' \
data/state/oshwhub_batch200_candidates.jsonl | paste -sd,)
ssh dev1 ... --backfill-source --uuids "$STD_UUIDS"
```
每项 ~5-10sStd 比 Pro 快doc 数少100 项 ~10 min。
### Step 5 — 附件下载(**可选 / 推迟**
batch-50 的 50 项声明附件 2.36 GB外推 batch-200 ~9-10 GB。Gitea LFS 当前用量 < 5 GB加 10 GB 还在舒适区。
但下载时间是关键因素:
- 200 项 × 平均 50 MB 附件 / 5 MB/sdev1 → image.lceda.cn 估算)= ~30 分钟
-`--skip-ext mp4,qt,mov` 可砍 30-50% 体积
**建议**:先做 Step 1-4 拿到 license + source附件单独评估后再决定。如果只为 EPRO2 → KiCad 训练,附件不需要。
### Step 6 — 验收 + push
```bash
ssh dev1 'cd ~/repo/FacereDataset && \
uv run python scripts/build_index.py && \
git add data/raw/oshwhub/ projects.md && \
git commit -m "batch-200: ..." && \
git push origin main'
```
---
## 5. 资源预算
| 项 | 估算 | 备注 |
|---|---:|---|
| API 调用 | ~2,500 次 | 200 详情 + 100 Pro × 5 calls + 100 Std × 5 calls + chain blob 几百次 |
| dev1 walltimeStep 1-4| **~25-35 分钟** | 单 IP 串行;加 backfill concurrency 可压到 10-15 min |
| 源工程体积 | **~2.5 GB** | batch-50 实测 12 MB/项 × 200 = 2.4 GB |
| Gitea pushdev1 SSH 链路)| ~3-5 min | 同 batch-50 量级SSH transport 健康 |
| 附件(如做 Step 5| +10 GB / +30 min | 可砍 mp4 节流 |
| **LFS 总增量(不含附件)** | **~2.5 GB** | 当前 < 5 GB → batch-200 后 ~7-8 GB |
| **LFS 总增量(含附件)** | **~12 GB** | → 批后 ~17 GB离 200 GB 迁移线还远 |
## 6. 风险与预案
| 风险 | 概率 | 影响 | 预案 |
|---|---|---|---|
| Pro cookie 过期半路 | 低 | 100 项 Pro 可能多个失败 | 已在 dev1 + SG 同 cookie过期表现是连续 401监控前 5 个失败即停 |
| 单 Pro 项目超 200 MB | 低 | size cap 触发跳过 | `--max-source-mb 200` 拦截,记 oversize state |
| Pro 2.x 又出现新边缘 case非 deprecated-board| 中 | 单项 fail | 当前 fix 处理 deprecated 类;新 case 用 try/except 单点收敛后 retry |
| 附件 mp4 视频拉爆磁盘 | 中(如做 Step 5| 多消耗 5+ GB | `--skip-ext mp4,qt,mov` |
| dev1 → gitea 链路波动期间 push | 中 | 需手动重试 | 已切 SSHBBR 已开;最差 retry |
| 触发 oshwhub 限流 | 低 | 整批中断 | 现有 sleep 已在实测水位;监控 200/non-200 比例,连续 3 个 5xx 即停 |
## 7. 验收标准
- [ ] `data/raw/oshwhub/` 新增 ≥ 195 个项目目录(允许 ≤ 5 项 fail
- [ ] 每个新增项目的 `metadata.json``license` + `source_format` + `source_path`
- [ ] license 分布盘点写入 log
- [ ] `projects.md` 自动重建后包含全 265 项
- [ ] LFS 增量 < 5 GB不含附件/ < 15 GB含附件
- [ ] log.md 顶部一条总结性日志
- [ ] dev1 push 整批 ≤ 10 min wall
## 8. 后续候选
- **batch-500** —— 把 A 档2,741 项)一次性吃完(剩 ~2,540
- **B 档grade≥2 & like≥5扩量** —— 总池子 ~6,243 项
- **附件细分策略** —— 按 ext 分类 LFSGerber/STEP 留、视频走外链)
- **Pro 2.x → KiCad 解析链路** —— 复用 `easyeda2kicad.py`plan.md §1.7 提过但未做)
- **license 详情扫全 A 档** —— 全 2,806 项 license 落本地,给所有未来批选作过滤依据