feat: 采集插件整合进OSK

This commit is contained in:
R524809
2026-08-27 17:18:50 +08:00
parent bb8f235e34
commit efe3474deb
41 changed files with 9704 additions and 128 deletions
+5 -5
View File
@@ -58,7 +58,7 @@ V2(原计划) V2.1(现在)
| 编号 | 决策 | 内容 | 理由 |
|---|---|---|---|
| **D1** | 放弃 Ozon API 直传 | `server/api/publish.py``services/publish.py`、店铺/类目代理等发布链路代码**保留但冻结**,不作为主链路;上品方式 = CSV 导出 + 人工后台录入 | ImportProductsV3 字段对齐工作量对个人不可承受;人工上品每品只花几分钟 |
| **D2** | 采集以 image-suite-studio 为主要参考 | 采集引擎(collector/profiles/平台文件)、页内悬浮面板 UI、三平台覆盖(Ozon/1688/淘宝天猫)全部以 `../image-suite-studio/extension` 的实现为准 | 该项目已跑通三平台商详页采集(Ozon 四路径降级 + 阿里系 MAIN-world 桥),且与本仓 extension-v2 同源,合并成本低 |
| **D2** | 采集以 image-suite-studio 为主要参考 | **(方案三,已实施)ISS 扩展整体并入主仓 `extensions/collector/`,成为唯一采集工具;扩展新增「上报商品」(POST /api/materials + 自动打开 /trial/{id});extension-v2 原地冻结** | ISS 已跑通三平台采集;单仓维护避免引擎分叉;ISS 独立产品化远期靠构建/配置裁剪,不在代码层分叉 |
| **D3** | 采集完成双动作 | 上传 `/api/materials` 入库(已实现)+ 插件自动打开 `{studio}/trial/{product_id}` | 采集即进入试算流水线,减少手工跳转 |
| **D4** | 商品试算页 studio 化 | 新增 `/trial/:id` 页面,功能与操作流水线对齐 `web/ozonSeller.html`(计价/俄文文案/图片水印/采购地址/登记/CSV/组合码),数据从 localStorage 升级为 products 表落库 | web/ v1 已验证好用,冻结只读;studio 是其 React+antd 版本 |
| **D5** | 图片生成对齐 image-suite-studio | 套图规划(DeepSeek)→ 一键生成(多 provider 模型路由:豆包/通义/RightAPI)→ 服务端水印 → 导出 ZIP;生成图回写 `product_assets(generated)` | 套图能力已在 image-suite-studio 验证;服务端代码整体平移复用 |
@@ -118,10 +118,10 @@ V2(原计划) V2.1(现在)
| 阶段 | 内容 | 状态 |
|---|---|---|
| **Phase A(本次)** | docs/v2.1 方案文档 + 试算页前端(路由/入口/5 区块/服务层契约) | ✅ 本次交付 |
| **Phase B** | 服务端:`/api/suite/*``/api/suites/*``/api/export/images``/api/proxy-image`(从 image-suite-studio/server 平移 generator/planner/prompts/watermark/tasks/storage | 待开工 |
| **Phase C** | 插件:extension-v2 的 collector/profiles/面板对齐 image-suite-studio(补 1688/淘宝、页内悬浮面板),采集成功后自动打开 `/trial/{id}` | 待开工 |
| **Phase D** | 打磨:批量 CSV 服务端化、生成图自动回写素材、水印增强(拖动定位/白底处理评估移植 web v1 能力)、组合码批量导出优化 | 待开工 |
| **Phase A** | docs/v2.1 方案文档 + 试算页前端(路由/入口/5 区块/服务层契约) | ✅ 完成 |
| **Phase C** | 采集对接:ISS 扩展并入 `extensions/collector/` + 「上报商品」开关 + 自动打开试算页(方案三,见 collect.md) | ✅ 完成 |
| **Phase B** | 服务端:从 ISS server 平移 planner/generator/prompts/watermark/tasks/api/suite/*、/api/suites/*、/api/export/images、/api/proxy-image),打通试算页一键生成与单张 AI 生图 | 待开工 |
| **Phase D** | 打磨:批量 CSV 服务端化、生成图自动回写素材、水印增强、ISS-only 产品模式构建配置 | 待开工 |
每个阶段结束都可独立运行:Phase A 结束时,试算页的计价/文案/素材上传/入库立即可用(对接已有接口),套图相关按钮点击会提示「服务端接口未实现」。
+48 -83
View File
@@ -1,109 +1,74 @@
# V2.1 采集方案(以 image-suite-studio 为主要参考
# V2.1 采集方案(扩展并入主仓 + 上报开关
> 状态:方案定稿Phase C 实施
> 状态:已实施Phase C 完成
> 参考项目:`/Users/joey-xd/sites/seller-store/image-suite-studio`(下称 ISS
> 原则:**采集功能以 ISS 的实现为准**。ISS 的采集引擎本就与本仓 extension-v1/v2 同源,V2.1 把 ISS 的最新版采集实现(含 1688/淘宝与页内悬浮面板)合并回本仓,并接上本仓已有的服务端上传链路。
> 架构(方案三,D2 决策修订):**ISS 扩展整体并入主`extensions/collector/`**,成为唯一采集工具
> extension-v2 原地冻结、不再维护);扩展新增「上报商品」功能,采集后一键入库主仓后台并自动打开商品试算页。
> 「ISS 独立产品化」远期通过构建/配置裁剪实现(扩展天然独立分发;server 的 suite API 模块不依赖 products),
> 不在代码层分叉——这是「单仓维护」与「独立产品可能」的折中。
---
## 1. 采集形态与架构(照搬 ISS
Chrome MV3 扩展(WXT + React + antd),四个 content script 注入三个平台的四个站点:
| 站点 | 匹配 |
|---|---|
| Ozon | `*.ozon.ru` / `*.ozon.kz` / `*.ozon.by` |
| 1688 | `detail.1688.com` |
| 淘宝/天猫 | `item.taobao.com` / `detail.tmall.com` |
## 1. 目录与形态
```
extension/
├── entrypoints/
── background.ts # Service Worker,唯一出网口(上传/代理 fetch
│ ├── content/index.ts # 采集脚本(isolated world),挂 window.__SuiteCollector
│ ├── bridge.content.ts # MAIN world 桥:postMessage 读页面全局变量(window.context / __ICE_APP_CONTEXT__
│ └── panel.content.ts # 页内悬浮按钮「套」+ 右侧滑出面板(Shadow DOM + iframe 懒加载
── src/
│ ├── collector/ # 采集引擎(见 §2)
│ ├── profiles/ # 声明式站点配置(ozon/1688/taobao
│ ├── api/client.ts # 上传 payload 组装
│ └── storage/settings.ts# baseUrl/token/水印设置
└── entrypoints/sidepanel/ # 面板 UIApp.tsxiframe 复用)
ozon-seller-kit/
├── extensions/ # Chrome 插件集合(复数,容纳未来多个插件)
── collector/ ← ISS 扩展并入版(三平台采集 + 套图生图面板 + 商品上报
├── extension-v1/ # 冻结(旧 1688/淘宝)
├── extension-v2/ # 冻结(旧 Ozon 采集,被 collector 取代
├── server/ # 唯一后端(8800
── studio/ # 前端(试算页等)
```
UI 交互形态采用 ISS 的**页内悬浮面板**(在商品页右侧滑出,iframe 加载 sidepanel.html),
比 Chrome 原生 Side Panel 更贴近「边看商品边采集」的操作。
- 构建:`pnpm -C extensions/collector build``.output/chrome-mv3`Chrome 开发者模式加载 unpacked
- 扩展包名:`ozon-collector-extension`;manifest 名保留「电商套图工作台」
- host_permissions 已加 `127.0.0.1:8800`(上报)与 `8900`(试算页)
## 2. 采集引擎(多源合并,主路径优先、DOM 兜底
## 2. 采集引擎(与 ISS 完全一致,见下表
统一入口 `src/collector/scan.ts``scanCurrentPage()``matchProfile(location.href)` → 分发平台文件 → `merge.ts` 装配 `ScanResult`
| 平台 | 主路径 | 兜底/补充 |
|---|---|---|
| **Ozon** | ① SSR `data-state` widget 白名单 | ② JSON-LD ③ 站内 `entrypoint-api.bx`(两 URL 合并)④ DOM + 模拟滚动 |
| **淘宝/天猫** | ① MAIN world 桥读 `__ICE_APP_CONTEXT__`(不调 mtop 防风控) | ② DOM(前缀匹配类名、详情图排除评价区;desc 故意不采) |
| **1688** | ① MAIN world 桥读 `window.context`deepFindskuProps 全维展开 + skuMapOriginal + 尺寸重量参数) | ② DOM(`#productAttributes` cells、`#detail` |
| 平台 | 主路径 | 兜底/补充 | 关键实现(ISS 路径) |
|---|---|---|---|
| **Ozon** | ① SSR `data-state` widget 白名单(webGallery/webPrice/webProductHeading/webShort\|Detailed\|Characteristics/webAspects/webReviewProductScore/breadCrumbs | ② JSON-LD ③ 站内 `entrypoint-api.bx` JSON(两 URL 合并:默认页 + `?layout_page_index=2` 描述页)④ DOM 选择器 + 模拟人工滚动触发懒加载 | `collector/ozon-state.ts``jsonld.ts``ozon-api.ts``platforms/ozon.ts` |
| **淘宝/天猫** | ① MAIN world 桥读 `__ICE_APP_CONTEXT__`loaderData…item/skuBase/priceVO/参数表;SKU 缺失从 `__general_skupanel_cache_data` 容错深搜;**不调 mtop 签名接口防风控** | ② DOMCSS Modules 前缀匹配 `[class*="mainTitle--"]`;详情图 `excludeWithin` 排除评价/推荐;**desc 故意不采**) | `collector/taobao-state.ts``ssr.ts``platforms/taobao.ts` |
| **1688** | ① MAIN world 桥读 `window.context`deepFind BFSgallery/tempModel/skuModel.skuProps 全维展开 + skuMapOriginal 价格库存 + pieceWeightScaleInfo 自动生成尺寸重量参数/productAttributes | ② DOM`#productAttributes` cells 模式参数表、`#detail` 详情图) | `collector/1688-state.ts``platforms/1688.ts` |
采集数据结构 ScanResult`{ platform, itemId, url, texts[], images[], breadcrumbs?, stats, warnings, source }`texts: kind/content/pairsimages: groupKey/groupName/variantName/url/index/type)。
通用提取器(照搬):`text.ts`join/first/table/cells 四模式)、`image.ts`srcProps 降级链 + srcset 挑最大 + Shadow DOM 穿透 + SKU 按 `url::规格名` 去重)、`url.ts`(原图还原:Ozon `/wc\d+/`、阿里 `xxx.jpg_400x400.jpg → xxx.jpg``toThumbUrl` 反向缩略图)、`merge.ts`primary 先入 fallback 填缺,按 dedupeKey 去重,重排 main→sku→detail→video)。
### 采集数据结构(ScanResult,与 ISS 完全一致)
```jsonc
{
"platform": "ozon | 1688 | taobao",
"itemId": "…|null", "url": "…", "scannedAt": 1724000000000,
"source": "state | ssr | jsonld | api | dom | mixed",
"breadcrumbs": [ { "name": "…", "href": "…", "searchCategoryId": 7041 } ], // 仅 Ozon
"stats": { "main": 8, "sku": 6, "detail": 12, "video": 1 },
"warnings": ["详情图为 0 张,请滚动到页面底部后重新采集"],
"texts": [ { "kind": "title|price|params|selling_point|desc|brand|sales|shop",
"content": "…", "pairs": [ { "key": "材质", "value": "PP塑料" } ] } ],
"images": [ { "key": "main-001", "groupKey": "main", "groupName": "主图",
"variantName": "粉色", "url": "原图URL", "thumbUrl": "缩略图URL",
"index": 0, "type": "img|video", "width": 800, "height": 800 } ]
}
```
## 3. 采集后双动作(V2.1 新增)
ISS 采集完是「本地展示 + 生图」,本仓在其后追加落库与跳转:
## 3. 商品上报(v2.1 新增)
```
快速采集(悬浮面板)
│ scanCurrentPage() → ScanResult
快速采集(页内悬浮面板 / Side Panel
│ scanCurrentPage() → ScanResult(面板内可编辑标题/尺寸/重量/描述)
① 同步到采集箱:POST /api/materials(本仓已实现
payload = { platform, item_id, url, texts, images: [{url, group_key, variant_name, dedupe_key, width, height, type}] }
响应 { product_id, created } ← 服务端已有返回,插件此前未用,Phase C 起使用
「上报商品」按钮(01 商品信息区块下方;设置里可开关
POST {reportBaseUrl}/api/materials
payload = { source: {platform, itemId, url, collectedAt},
│ texts: editedTexts(), // 编辑后文本
│ images: 全量采集图(groupKey/groupName/variantName/url/index/type,
│ refererOrigin: 源页 origin } // 服务端下载源图带 Referer
② 自动打开商品试算页:chrome.tabs.create({ url: `${studioBaseUrl}/trial/${product_id}` })
│ studioBaseUrl 存插件设置(默认 http://localhost:8900
面板内提示「已入库并打开试算页」,用户可直接在试算页继续流水线
响应 { product_id } → chrome.tabs.create 打开 {studioBaseUrl}/trial/{product_id}
```
要点:
- `POST /api/materials` 的 texts/images 契约已对齐 ScanResultextension-v2 现有 `buildMaterialsPayload` 可直接复用)。
- 重复采集同一商品:服务端按 `platform + item_id` 复用 Product(已实现),插件拿到同一 `product_id`,打开试算页即回到原商品。
- 1688/淘宝素材上传:`_apply_texts` 平台无关,参数表/重量/尺寸解析已兼容(`_apply_weight_dims` 的 kg→g、cm→mm 换算同样适用 1688 的 `pieceWeightScaleInfo`)。
- **契约**:主仓 `MaterialsRequest`camelCase`source.itemId``groupKey``variantName`)与 ISS ImageMaterial 字段同名,直接映射;响应 `product_id` 用于打开试算页
- **重复上报**:服务端按 `platform + itemId` 复用商品(返回同一 product_id)→ 打开同一试算页
- **鉴权**:本地阶段主仓为宽松模式(未带 token 放行匿名),扩展直接裸调;远期收紧时在扩展 settings 加 token 即可
- **设置项**(面板「服务端设置」弹窗内新增):启用商品上报开关 / OSK 后台地址(默认 `http://127.0.0.1:8800`/ 试算页地址(默认 `http://localhost:8900`
- 手动上传图(ISS 的 upload 组合)本期不上报;试算页内可用「上传图片」补(`/api/materials/bytes`
## 4. extension-v2 改造清单(Phase C
## 4. 面板能力(保持 ISS 原样
| # | 改动 | 说明 |
|---|---|---|
| 1 | 用 ISS 的 `src/collector``src/profiles``src/bridge` 整体替换 extension-v2 对应目录 | ISS 版本更新(含 1688/淘宝 + 多项修复),以 ISS 为准 |
| 2 | 新增 `panel.content.ts` 页内悬浮面板入口 | 保留原生 Side Panel 入口,两种方式共存 |
| 3 | 面板 UIsidepanel/App.tsx)以 ISS 版为基线,去掉「出图方案/生成结果」区块 | 生图移到试算页做(屏幕更大、可对照商品信息);面板保留:采集结果核对/编辑、勾选图片、上传、下载采集图 |
| 4 | 上传成功后读响应 `product_id``chrome.tabs.create` 打开 `{studio}/trial/{product_id}` | 设置项 `studioBaseUrl` |
| 5 | background 保持唯一出网口(代理图片 fetch 绕防盗链 + 上传) | 已是现状 |
| 6 | `GET /api/collected?platform=&itemId=` 采集前查重提示 | 已有接口,面板显示「已采集过,将打开原商品」 |
快速采集、商品信息编辑、图片勾选/上传/下载、AI 智能规划、风格/生图要求/模型选择、一键生图、生成结果导出——全部保留,仍连 ISS 生图 server(`baseUrl`,默认 3300)。
后续 Phase B 把生图服务端平移进主仓后,`baseUrl``reportBaseUrl` 可统一指向主仓。
## 5. 与 ISS 的差异总表
| 维度 | ISS | 本仓 V2.1 |
| 维度 | ISS(独立项目) | 本仓 extensions/collector |
|---|---|---|
| 采集引擎 | 三平台完整版 | **相同**Phase C 平移 |
| 采集结果去向 | 仅面板展示(无持久化) | 落库 products/product_assets(复用 V2 已实现 |
| 生图入口 | 面板内 03/04 区块 | 移到 studio 试算页(功能对齐 + 单张 AI 生图增强) |
| 生图后端 | 独立 server(3300 端口,无鉴权) | 并入本仓 server8800JWTPhase B 平移 |
| 采集后动作 | | 入库 + 自动打开 `/trial/{id}` |
| 采集引擎 | 三平台完整版 | 相同(整体并入 |
| 生图面板 | 连 ISS server3300 | 同左(Phase B 后可切主仓 |
| 商品入库 | 无 | 「上报商品」→ 主仓 /api/materials + 自动打开试算页 |
| 鉴权 | 无 | 本地宽松模式(远期收紧 |
| 独立产品化 | 本体 | 远期:构建/配置裁剪出 collector + suite API 即可独立 |