From bfc1caac0064420acbdbf2013c99ef1afc2d3e0a Mon Sep 17 00:00:00 2001 From: admin9webs Date: Mon, 21 Sep 2026 08:57:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A6=99=E6=89=8B=E5=AF=BC=E5=85=A5=E9=87=87?= =?UTF-8?q?=E9=9B=86=E6=89=93=E9=80=9A=EF=BC=9Axls=208=20=E5=88=97?= =?UTF-8?q?=EF=BC=88=E4=BA=A7=E5=93=81=E4=B8=BB=E7=BC=96=E5=8F=B7/?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=9C=B0=E5=9D=80/=E6=A0=87=E9=A2=98/?= =?UTF-8?q?=E8=B4=A7=E5=B8=81=E7=B1=BB=E5=9E=8B/SKU=E5=94=AE=E4=BB=B7/SKU?= =?UTF-8?q?=E5=BA=93=E5=AD=98/=E4=BB=B7=E6=A0=BC/=E4=BF=83=E9=94=80?= =?UTF-8?q?=E4=BB=B7=EF=BC=89=E8=A7=A3=E6=9E=90=E6=88=90=E5=8A=9F=2047/0/4?= =?UTF-8?q?7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 妙手建品/RECIPE.md | 29 +++++++++++++++++++++++++++++ 妙手建品/ms_items.mjs | 20 ++++++++++++++++++++ 妙手建品/ms_reason.mjs | 20 ++++++++++++++++++++ 妙手建品/示例-ms2.xls | Bin 0 -> 17920 bytes 4 files changed, 69 insertions(+) create mode 100644 妙手建品/ms_items.mjs create mode 100644 妙手建品/ms_reason.mjs create mode 100644 妙手建品/示例-ms2.xls diff --git a/妙手建品/RECIPE.md b/妙手建品/RECIPE.md index de78f2a..d67dcca 100644 --- a/妙手建品/RECIPE.md +++ b/妙手建品/RECIPE.md @@ -130,3 +130,32 @@ await c.send('DOM.setFileInputFiles', { files: ['/path/ms_import.csv'], nodeId } ### 当前队列状态 已导入文件列表里有 3 条失败任务(`ms_import` / `ms_import2` / `ms_nobom`),可在页面上「删除文件」清掉。 + +## ✅✅ 导入链接采集终于通了:`ms2.xls` 解析成功 47/0/47(2026-09-21 08:55) + +### 能用的 .xls 表头(**照抄这 8 列**) +| 列 | 示例值 | 说明 | +|---|---|---| +| `产品主编号` | `548459586741` | 1688 商品 id,**必须**有 | +| `链接地址(必填)` | `https://detail.1688.com/offer/548459586741.html` | 采集源链接 | +| `产品标题` | 英文标题 | 可留空(留空以来源为准) | +| `货币类型` | `CNY` | **必须**;空值报「不允许此货币类型」 | +| `SKU售价` | `34.0` | **必须 ≥ 0.01**;空值报「必须大于等于0.01」 | +| `SKU库存` | `999` | **必须 ≥ 0** | +| `价格(RMB)` | `34.0` | 模板原有列 | +| `促销价(RMB)` | 空 | 模板原有列(表头提示:仅可用于采集到 Lazada) | + +### 关键结论(下一轮别再走弯路) +1. **必须是 `.xls`/`.xlsx` 二进制表格**——CSV 一律只报「未识别到【产品主编号】表头」,`txt` 走 JSON 也走不通; +2. **页面下载的模板是旧的**:它只有 4 列、**缺 `产品主编号`**,照它填一定失败 + (错误提示会写「请下载最新模版」,但最新模板实际要的就是上面这 8 列); +3. 生成脚本:`pip install --break-system-packages xlwt` → `xlwt.Workbook(encoding='utf-8')` → 写表头+47 行 → + 存 `.xls` → 用 `DOM.setFileInputFiles` 注入 `input.jx-upload__input` → 点「确认」; +4. 失败时**点「查看失败原因」**能看到逐行逐列的精确原因(这次就是靠它拿到 `货币类型/SKU售价/SKU库存` 三个列名)。 + +### 产物 +`/home/admin9webs/miaoshou/dl/ms2.xls`(47 行,可复用为模板);上传脚本 `ms_upload.mjs`; +状态查询 `ms_status.mjs`;失败原因 `ms_reason.mjs`。 + +### 下一步 +「查看导入产品」/ **公用采集箱** 里核对这 47 条采集结果,再验证子账号能否 `认领`/`发布`。 diff --git a/妙手建品/ms_items.mjs b/妙手建品/ms_items.mjs new file mode 100644 index 0000000..5b125f4 --- /dev/null +++ b/妙手建品/ms_items.mjs @@ -0,0 +1,20 @@ +import { listPages, wait } from '/home/admin9webs/shein建品/sh_lib.mjs'; +import { CDP, SAN as S } from '/tmp/cdp3.mjs'; +const t = (await listPages()).find(x=>/91miaoshou/i.test(x.url)); +const c = await CDP.connect(t.webSocketDebuggerUrl); +await c.send('Page.enable'); await c.send('Runtime.enable'); await wait(1200); +console.log('点查看导入产品:', String(await c.evalJS(`(()=>{ + const rows=[...document.querySelectorAll('tr')].filter(e=>e.offsetParent!==null&&/^\\s*ms2\\s/.test((e.innerText||'').trim())); + const row=rows[0]; if(!row) return 'no-row'; + const a=[...row.querySelectorAll('*')].find(e=>(e.innerText||'').trim()==='查看导入产品'); + if(!a) return 'no-link'; + for(const ev of ['mousedown','mouseup','click']) a.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 'clicked';})()`))); +await wait(7000); +const o = await c.evalJS(`(()=>{ + const rows=[...document.querySelectorAll('tr')].filter(e=>e.offsetParent!==null).map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).filter(Boolean).slice(0,5); + const tabs=[...document.querySelectorAll('[class*=tab]')].filter(e=>e.offsetParent!==null).map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim().slice(0,10)).filter(Boolean); + return JSON.stringify({href:location.href, rows, tabs:[...new Set(tabs)].slice(0,10), + body:(document.body.innerText||'').replace(/\\s+/g,' ').trim().slice(0,200)});})()`); +console.log('导入产品:', S(String(o)).slice(0,1000)); +try{ await c.shot('/tmp/ms_items.jpg'); console.log('shot ok'); }catch(e){} +process.exit(0); diff --git a/妙手建品/ms_reason.mjs b/妙手建品/ms_reason.mjs new file mode 100644 index 0000000..14a8f14 --- /dev/null +++ b/妙手建品/ms_reason.mjs @@ -0,0 +1,20 @@ +import { listPages, wait } from '/home/admin9webs/shein建品/sh_lib.mjs'; +import { CDP, SAN as S } from '/tmp/cdp3.mjs'; +const t = (await listPages()).find(x=>/91miaoshou/i.test(x.url)); +const c = await CDP.connect(t.webSocketDebuggerUrl); +await c.send('Page.enable'); await c.send('Runtime.enable'); await wait(1200); +console.log('点查看失败原因:', String(await c.evalJS(`(()=>{ + const rows=[...document.querySelectorAll('tr')].filter(e=>e.offsetParent!==null&&/^\\s*ms\\s/.test((e.innerText||'').trim())); + const row=rows[0]; if(!row) return 'no-row'; + const link=[...row.querySelectorAll('*')].find(e=>(e.innerText||'').trim()==='查看失败原因'); + if(!link) return 'no-link'; + for(const ev of ['mousedown','mouseup','click']) link.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); + return 'clicked';})()`))); +await wait(5000); +const o = await c.evalJS(`(()=>{ + const dlgs=[...document.querySelectorAll('.jx-dialog,.jx-drawer,[class*=dialog]')].filter(e=>e.offsetParent!==null) + .map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim().slice(0,500)).filter(Boolean); + return JSON.stringify({dlgs:dlgs.slice(0,2)});})()`); +console.log('失败原因:', S(String(o)).slice(0,1200)); +try{ await c.shot('/tmp/ms_reason.jpg'); console.log('shot ok'); }catch(e){} +process.exit(0); diff --git a/妙手建品/示例-ms2.xls b/妙手建品/示例-ms2.xls new file mode 100644 index 0000000000000000000000000000000000000000..b6d6e33b0aba33f10747c93468eba69ea85a6776 GIT binary patch literal 17920 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