问题:图片 key 是内容 sha1,不下载就无法判断是否已存在; 后端又没存 source_url,无法做 URL 级判重。 于是每次重爬都把几百张已下过的图再下一遍 —— 线上实测 Celine 跑了 62 分钟、约 600MB,入库 0 新增。 修复: - 后端新增 GET /admin/internal/shows/covered?brand_uid= 按 (年份, 季节, 类型) 聚合已入库图片张数 - spider 抓取前预检,整场已入库(>=10 张)就跳过,一张图都不下载 - 加 --force 可强制重抓(默认跳过) - 媒体直传并发改为全进程共享信号量:此前秀级 2 × 每场 6 = 12 路 同时打 Vogue,被限流后单张从 9.8s 掉到 ~90s - 批次下载失败时打印第一条错误(此前只统计个数,查不出原因)
spider
Vogue 走秀 / The Impression 街拍采集器。抓到的元数据经 HMAC 签名上报后端 ingest 接口,由后端异步下载图片、写库、编码向量——spider 不直连数据库。
两种运行模式
| 模式 | 命令 | 适用 |
|---|---|---|
| 单次抓取 | spider vogue -b <品牌id> [-s 场次上限] |
临时补某个品牌、调试 |
| 常驻服务 | spider serve -w 4 -i 5 -m 5 |
生产用法:从后台领取任务 |
服务模式不再由人指定品牌:后台决定爬谁(/admin/crawl),spider 领取并执行,执行结果回报后台。
配置(config.yml)
ingest:
enabled: true # serve 模式必须为 true
endpoint: "http://<后端IP>:8092/admin/internal/ingest"
secret: "<与后端 INGEST_SECRET 完全一致>"
hashid_secret: "" # 服务模式不需要(brand_uid 由后端下发)
endpoint末尾是/ingest,客户端会自己推导出/crawl/tasks(领取任务)和/crawl/tasks/:id/result(回报结果)。
媒体机直传(把下载/上传从前端搬出来)
media:
upload: true # 打开:spider 自己下载图并直传对象存储,后端只写库
concurrency: 6 # 下载/上传并发
打开后 spider 会:下载图片 → 按内容 sha1 生成 key(runway/<sha1>.jpg)→ 向后端
/admin/internal/upload-url 申请一次性 PUT 地址 → 直接上传 → 上报时只带 key。
关键点:
- 密钥只在后端:spider 拿的是 15 分钟有效的预签名 URL,不持有存储 AK/SK
- key 是内容寻址,重复上传幂等,重爬不产生孤儿文件
- 单张失败不影响整场:失败的图仍带原始 URL,后端会兜底下载
- 关掉
upload就完全回到旧行为(后端下载),可随时回滚
什么时候值得打开:spider 部署在带宽比后端机器好的地方时收益明显; 如果两者在同一台机器上,下载带宽是同一份,拆开不会更快(只是把活儿换个进程干)。
服务模式怎么跑
# 编译
go build -o spider .
# 启动:4 路并发、空队列每 5 秒轮询、单品牌内部并发 5
./spider serve -w 4 -i 5 -m 5
| 参数 | 含义 | 建议 |
|---|---|---|
-w/--workers |
同时跑几个品牌 | 带宽/CPU 够就 2~4;每个品牌内部还有 -m 并发 |
-i/--interval |
队列空时的轮询间隔(秒) | 5~10,别设 1(会把后台接口打满) |
-m/--max-co |
单品牌内部的抓取并发 | 3~8;太大会被 Vogue 限流 |
优雅退出:Ctrl+C 会停止领新任务,等手上的品牌跑完再退。
日志里每个任务有两行关键输出:
[serve] host-1234-0 领取任务 task=7 品牌=Acne Studios(uid=001AJGov) 场次上限=3
[serve] host-1234-0 任务 7 完成:status=done 提交 3 场,耗时 42s
单次模式(调试用)
./spider vogue -b 7 # 只抓 Gucci,不限场次
./spider vogue -b 7 -s 2 # 只抓最近 2 场
./spider vogue -d # debug:只打印,不上报
./spider theimpression -n 10 # 街拍,最多 10 条任务
-b 是数据库里的数字 id(brands.id),不是 hashid。
后台怎么操作
访问 http://<后端>:8092/admin/crawl(需先登录后台)。
1. 加任务
| 场景 | 操作 |
|---|---|
| 抓单个品牌 | 去 /admin/brands 找到品牌 → 点「加入抓取队列」(默认每品牌 3 场) |
| 批量抓一批 | 在 /admin/crawl 顶部「批量加入」:前缀 A + 场次上限 3 + 数量 50 → 就是把 A 开头的 50 个品牌各抓最近 3 场 |
| 重爬某个品牌 | 在任务列表该行点「重试」(会把状态重置为待领取) |
「场次上限」填 0 表示不限场次——批量时不要填 0,否则一个老品牌可能有上百场,一次灌进来几万张图。
2. 看状态
| 状态 | 含义 |
|---|---|
| 待领取 | 已入队,等 spider 来拿 |
| 执行中 | 某个 spider 已领取(列表里会显示 worker 标识) |
| 已完成 | 跑完了。已提交 列是本次提交了几场走秀 |
| 失败 | spider 侧进程级失败,会自动重试最多 3 次;耗尽后需手动「重试」 |
已提交 = 0 不一定是错误:Vogue 上很多品牌没有走秀页面(实测 A 开头品牌里约 75% 没有),这种情况任务是「已完成、提交 0 场」。
3. 取消 / 删除
- 取消:只是不再被领取,无法中断正在执行的品牌(spider 手里还在跑)
- 删除:只删任务记录,已入库的图集不受影响
4. 任务卡在「执行中」怎么办
正常情况会被自动回收:后台对 执行中 的任务有 15 分钟租约,超过仍未回报就自动放回「待领取」。所以 spider 断电/被杀不会导致任务永久丢失,重启后会被重新领走。
抓完之后
任务完成只代表元数据已提交。图片下载、写库、编码向量由后端 worker 异步完成,看进度去:
/admin/ingest-jobs— 入库任务(pending / processing / done / failed)/admin/articles— 已入库的图集(默认pending状态,前台不可见,需在列表里通过)
常见问题
| 现象 | 原因 / 处理 |
|---|---|
| 启动即报「ingest 未启用」 | config.yml 的 ingest.enabled 不是 true |
| 一直「无任务」 | 后台还没加任务,或全部被其他 spider 领走了 |
| 领取报 401 | ingest.secret 与后端 INGEST_SECRET 不一致 |
| 任务反复失败 | 看后台列表的「错误」列;常见是网络不通/被 Vogue 限流 |
| 抓到了但前台看不到 | 图集是 pending,去 /admin/articles 通过审核 |