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 (commitc3cac97) - SSH transport for dev1 -> gitea (commit8220c99) 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>
7.7 KiB
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 项概况
| 维度 | 值 |
|---|---|
| 总数 | 200(100 Pro + 100 Std) |
| 唯一作者 | 173(max 单作者 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)
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 分布盘点(无过滤入库)
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)
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)
STD_UUIDS=$(jq -r 'select(.origin=="std") | .uuid' \
data/state/oshwhub_batch200_candidates.jsonl | paste -sd,)
ssh dev1 ... --backfill-source --uuids "$STD_UUIDS"
每项 ~5-10s(Std 比 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/s(dev1 → image.lceda.cn 估算)= ~30 分钟
- 加
--skip-ext mp4,qt,mov可砍 30-50% 体积
建议:先做 Step 1-4 拿到 license + source;附件单独评估后再决定。如果只为 EPRO2 → KiCad 训练,附件不需要。
Step 6 — 验收 + push
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 walltime(Step 1-4) | ~25-35 分钟 | 单 IP 串行;加 backfill concurrency 可压到 10-15 min |
| 源工程体积 | ~2.5 GB | batch-50 实测 12 MB/项 × 200 = 2.4 GB |
| Gitea push(dev1 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 | 中 | 需手动重试 | 已切 SSH,BBR 已开;最差 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 分类 LFS(Gerber/STEP 留、视频走外链)
- Pro 2.x → KiCad 解析链路 —— 复用
easyeda2kicad.py(plan.md §1.7 提过但未做) - license 详情扫全 A 档 —— 全 2,806 项 license 落本地,给所有未来批选作过滤依据