店小秘多平台铺货配方:7 平台建品脚本 + 静默拦截诊断法 + 项目状态

- TikTok/Shopee/速卖通/Walmart 各 46-47 条已在待发布
- Ozon 47 条已建、改价 40/47
- SHEIN 配方跑通第一条;Temu 差「预览图」一步
- 核心产出:MYJ.message.error 钩子诊断法(解开了三个平台的保存静默拦截)
- 含下一轮提示词 NEXT-ROUND-PROMPT.md
This commit is contained in:
admin9webs committed 2026-09-20 17:29:38 +08:00
commit f5720ad613
94 files changed
+21561

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
# Temu 全托管(①Alimingpro, shopId 4021529)进展
## 已勘明
- 类目:1038 个,直接从 `temuAddBasicStore.dataState.categories` 读(不用滚动)
- 选类目:下拉需**先 scrollTop=0**(默认残留上次滚动位置)→ 滚动找 `.ant-select-item-option`
- 外包装形状:不规则 / 长方体 / 圆柱体
- 外包装类型:硬包装 / 软包装+硬物 / 软包装+软物
- 字段落点:
- `temuAddProductStore.formState.mainImage` → **数组**
- `temuAddProductStore.formState.materialImage` → **对象**(单个)
- `temuAddOtherStore.packageFormState` → `{packageShape, packageType, packageImages, inventoryRegion}`
- `temuAddSkuAttrStore.formState.skuAttrs` → `[{type:2,parentSpecId:1001,parentSpecName:"颜色",options:[]}]`
- `temuAddSkuDataStore.formState.skuDataList` → SKU 行
- 必填 9 项:店铺/分类/标题/产地/轮播图/素材图/外包装形状/外包装类型/外包装图片
## 未解(卡点)
1. 点「保存」不发任何 POST,且无校验红字 → 静默拦截
2. 程序化塞 `skuAttrs[0].options` **不生成** `skuDataList` 行(需走 UI)
3. 变种区只渲染出主题选择器(颜色/风格/材质…),**值输入控件没找到**;变种本身也非必填
4. `产品素材图` 在 DOM 里仍显示为空(store 已设)
5. 表单下方未发现价格/库存输入(可能随变种行生成)
---
## 更新:静默拦截已定位(用 MYJ.message.error 钩子)
Temu 被吞掉的报错是**层层递进**的:
1. ~~`产地选择中国时,省份必填,请完善后提交`~~ → 已解决
路径:`temuAddProductStore.formState.region2Id`(候选在 `region2Id` 同级 `regionCode`,31 个省)
注意:直接赋值 store 当时不生效,但**异步同步后 UI 会显示「北京市」**,再点保存即通过
2. **`产品变种不能为空!`** ← 当前唯一剩下的卡点
需要真正生成变种行(`temuAddSkuDataStore.formState.skuDataList`)
程序化塞 `temuAddSkuAttrStore.skuAttrs[0].options` **无效**
## 变种区控件(待继续)
- `.ant-select` #16 = 颜色主题选择器(主题候选:颜色/风格/材质/口味/…共18个)
- `.ant-select` #17 = 尺码
- 未找到独立的值输入框;值控件可能随主题选中后异步渲染
---
## 更新2:照 SHEIN 的解法推进,报错序列已剥到最后一层
Temu 的规格机制和 SHEIN **不同构**——没有 `theme-select-box`,
而是 **两个 `.theme-value-add` 块**(颜色 / 尺码),每块各有「值输入框(`input[class*="!w-200"]`) + 添加按钮」。
**值必须手动输进去再点「添加」**,程序化塞进 `skuAttrs[0].options` 完全无效。
### 报错序列(每修完一层才露出下一层)
| # | 报错 | 状态 | 解法 |
|---|---|---|---|
| 1 | 产地选择中国时,省份必填 | ✅ | `temuAddProductStore.formState.region2Id`(异步同步,需再点一次保存) |
| 2 | 产品变种不能为空! | ✅ | 两个 theme-value-add 各输一个值点「添加」→ `skuDataList` 生成 2 行 |
| 3 | 尺寸不能为0或空 | ✅ | SKU 表「尺寸(cm)」列每行有 **3 个子输入**(长/宽/高),要全填 |
| 4 | 净重必须小于重量 | ✅ | 净重填 90、重量填 100(不能相等) |
| 5 | **请上传预览图** | ⬜ 当前 | SKU 表「预览图」列需真实图片,不是文本 |
### SKU 表列(Temu 全托管)
`预览图 | 颜色 | 尺码 | SKU货号 | EAN UPC ISBN | 申报价格(CNY) | 尺寸(cm) | 重量(g) | 净重(g) | 建议售价 | SKU分类`
⚠️ EAN 用公司台账下一段:pc 3447 起(Walmart 已用 3400~3446)
+479
View File
@@ -0,0 +1,479 @@
[
"墙壁装饰图案",
"遥控器",
"瓷砖贴玻璃贴",
"活页夹、回形针",
"纽扣",
"美发刷",
"线缆收纳包和盒子",
"护照夹、证件包",
"行李牌",
"女士钥匙环、钥匙链",
"急救包",
"手工艺胶带",
"牙刷架",
"登山扣饰和钥匙扣",
"创可贴",
"圆环活页夹",
"其他(男装配饰)",
"其他(墙贴和壁饰)",
"办公隔间挂钩",
"女士瑜伽瑜伽袜",
"鼠标垫",
"彩色文件夹",
"手机装饰品",
"女士胸针、领针、丝巾扣",
"学科笔记本",
"汽车挂饰",
"别针夹子盒",
"桌面订书机",
"手动卷发器",
"化妆粉扑和海绵",
"MP3 播放器保护套和外壳",
"男士眼镜盒",
"头发定型别针",
"气球",
"其他(化妆工具)",
"荧光笔",
"记事簿",
"笔记本电脑贴花",
"安全别针",
"剪刀",
"其他(橡皮)",
"贺卡",
"反光衣/反光安全装备",
"其他(包裹耗材)",
"挤压玩具",
"婴幼儿抽屉锁",
"水族馆装饰主题摆件",
"其他(新奇玩具)",
"女士时尚束发带",
"辅助挂钩",
"盥洗洗漱包",
"头发侧梳",
"油漆笔和马克笔",
"记事簿配件",
"电话支架",
"空白标签牌",
"便携式包袋挂钩",
"搞笑整蛊玩具",
"其他(发型设计配件)",
"女士薄丝袜",
"美工刀",
"削笔刀",
"其他(日历及个人规划用品)",
"胶水胶棒",
"其他(教学耗材)",
"线缆带",
"其他(教室装饰)",
"棉签",
"拉链",
"女婴袜子",
"化妆品收纳盒",
"书立",
"自行车把套",
"自行车喇叭",
"门档",
"耳塞",
"海绵",
"鞋垫",
"午餐包、午餐袋",
"工艺扇",
"女婴发夹",
"吉他背带",
"冰块模具和托盘",
"活页纸",
"其他(办公家具配件)",
"明信片",
"其他(马克笔荧光笔标记笔)",
"办公簿册装订环",
"图钉",
"手机挂绳与腕带",
"智能手机拉环支架",
"眉毛修剪器",
"抽绳健身包",
"洗脸毛巾",
"其他(钓鱼用品)",
"室内装饰石",
"手动牙刷",
"保险杠贴纸",
"扁平餐具收纳",
"行李整理包",
"起钉器",
"卷尺",
"直尺",
"自动铅笔",
"绘图工具和套件",
"显示器支架",
"办公纸夹",
"办公胶带座",
"工艺粘合剂打蜡",
"脱毛镊子",
"其他(飞钓饵)",
"小雕像摆件",
"女士时尚垂坠式耳环",
"其他大家电配件",
"杯垫",
"玻璃贴膜",
"礼品袋",
"卡纸",
"流苏",
"自行车水壶架",
"真空压缩袋",
"奶嘴链",
"透明胶",
"睫毛膏",
"化妆造型用品",
"女士发带",
"纸张打孔器",
"隔页板",
"木质印章",
"书托架",
"其他(信封)",
"办公家具靠垫、坐垫",
"指南针",
"其他(男士袜子)",
"急救胶带",
"搓澡巾",
"舌刷、舌刮",
"其他(派对装饰)",
"猫薄荷玩具",
"其他(益智思维游戏)",
"女童新奇钱包",
"口袋插笔套",
"面部装饰贴",
"礼品包装袋",
"瓶塞",
"圆髻和皇冠发型成型器",
"可再填充的化妆品喷雾瓶",
"缝纫绳扣和调节扣",
"化妆刷套件",
"内衬袜、船袜",
"齿间牙签",
"车用香水、空气清新",
"三环装订相册",
"美甲模板",
"装饰挂钩",
"棒棒糖、蛋糕模具",
"手动头部按摩器",
"化妆刷清洁用品",
"办公收纳用品",
"切纸机刀片",
"键盘托架",
"桌面吸尘器",
"钱袋",
"文具记事本",
"橡皮擦",
"自行车座杆",
"其他(健身、训练用品)",
"儿童画画衣",
"微型创意玩具",
"男婴袜子",
"汽车摆件",
"眉笔、眉粉",
"清洁刷",
"浇水壶",
"眼影刷",
"多用工具",
"嫁接睫毛工具",
"马桶垫",
"手工折纸",
"女士腰带",
"手机防水袋",
"蜡式脱毛刮片",
"拉力带",
"其他(皮肤护理)",
"时尚、休闲腰包",
"粉底刷",
"其他(手机配件)",
"折纸",
"毛球、绒毛去除器",
"食品过滤器",
"装饰纸花球",
"手机支架",
"悬挂式鞋子收纳袋",
"保湿脚套",
"帽子",
"阿育吠陀香膏和药膏",
"猫清洁按摩刷",
"婴幼儿防撞用品",
"女士情趣连体衣、连体袜",
"烫衣板",
"其他(女婴发饰)",
"女士钱包",
"口红",
"化妆品",
"婴幼儿温度计",
"S形挂钩",
"其他(清洁工具)",
"办公室计算器配件",
"其他(商务公文包及电脑包)",
"其他(切纸刀)",
"双肩电脑包",
"高线画笔",
"粘合剂、胶水",
"笔式橡皮",
"强力胶",
"索引卡归档和名片归档",
"钥匙箱",
"快递文件袋",
"针尖式水笔",
"D环活页夹",
"女士小腿袜",
"医用压缩丝袜",
"茶包碟",
"固定夹",
"茶勺",
"个人用电风扇",
"压蒜器、蒜泥器",
"钩子线",
"狗飞盘",
"手指套",
"运动风汽车贴纸",
"下水道疏通器",
"编织制作工具",
"狗保护罩",
"女士新奇短袜",
"女婴帽子",
"角色扮演骰子",
"运动胶带、绷带",
"其他(大家电配件)",
"后变速器",
"化妆镜",
"生日蜡烛",
"派对用品套装",
"食物存放和整理套装",
"电源转换器",
"手写笔",
"透明印章",
"女童装扮假发",
"墙纸、壁纸",
"其他(挂件吊饰)",
"钓鱼帽",
"派对钥匙圈礼品包",
"女士斜挎包",
"狗用理容梳",
"女士盒剃刀",
"双眼皮贴",
"其他(饰品收纳)",
"口腔温度计",
"垃圾袋收纳器",
"毛绒动物配件",
"自行车配件",
"百洁布",
"其他(刷子)",
"睡袍和浴巾挂钩",
"小便池配件",
"马桶刷、架",
"游泳鼻夹",
"渔具卡扣",
"磨脚石",
"门吊挂钩",
"首饰托盘",
"门锁",
"行李秤",
"旅行鞋子收纳包",
"吉他拨片",
"展示画架",
"马桶替换件",
"女士时尚贴颈项链",
"女士户外袜子",
"胶粘防撞垫",
"男士新奇补丁贴布",
"车迷钥匙链",
"男士运动束发带",
"日常脚部和指甲护理产品",
"其他(面部护理工具)",
"倒酒器",
"商用去毛器",
"USB 数据线",
"其他(派对装饰品和用品)",
"替换胶绵",
"手动背部按摩器",
"PlayStation Vita 保护套",
"其他(熨烫用品)",
"束发带",
"时尚束发带",
"加长型睫毛膏和打底膏",
"女士运动紧身袜",
"化妆棉",
"日用鞋扣和鞋带辅助用品",
"室内灯串",
"水烟炭夹具",
"缠绕护膝/缠绕运动绷带",
"烧烤工具套件",
"指甲清洁刷",
"其他(端口转接头)",
"女孩钱包",
"洒水器",
"男士新奇钥匙链",
"日程表本",
"挂孔纸",
"考勤卡",
"手提、单肩电脑包",
"男士证件夹",
"扫描仪配件",
"可清除标签",
"文件夹标签",
"信件和信笺横格纸",
"校对夹",
"杂志架",
"其他(索引卡归档产品)",
"木制彩色铅笔",
"其他(运动医学产品)",
"管道胶带",
"多功能书写工具",
"圆规",
"织物胶粘剂、粘合剂",
"圣诞袜、节日装饰袜",
"女袜袜套",
"笔记本散热器",
"女士围脖",
"儿童装扮面罩",
"一次性吸管",
"水族箱入门套件",
"其他(键盘乐器配件)",
"公用叉勺服务餐具套装",
"其他(装扮珠宝首饰)",
"摩托车头盔面罩",
"飘带",
"手机防尘插头",
"雕刻刀",
"发条、弹簧类玩具",
"挞盘",
"婴幼儿牙刷",
"拼图游戏",
"女婴半身裙、裙裤",
"其他(女童服饰配件)",
"汽车牌照套",
"其他(女童帽子)",
"大码女士薄丝袜",
"女婴连指、分指手套",
"安抚奶嘴",
"牙胶",
"粘土",
"游泳耳塞",
"锅具配件",
"毛绒公仔",
"女士腕包",
"相片角贴",
"专业水笔",
"女士时尚个性戒指",
"锅盖架",
"烤炉垫和地垫",
"邮差包",
"其他(眼睛护理)",
"指甲刷",
"指甲油固化灯",
"药丸压碎器和切药丸器",
"收纳篮",
"洗车工具",
"灶具旋钮",
"其他(面部护肤)",
"防磨脚贴",
"熨衣板盖",
"家庭马桶清洁剂",
"男士项链",
"实验室洗瓶",
"其他(工艺品和缝纫用品储物)",
"眼罩",
"空白便条卡套装",
"装饰性铃",
"其他(女士手提包和钱包)",
"相机隐私保护盖",
"仿真食物",
"中转袋",
"眼线刷",
"女士时尚珠子吊饰",
"熨烫配件",
"钢丝刷",
"浴衣和毛巾挂钩",
"婴幼儿指甲刀",
"空顶遮阳帽",
"男士户外帽子",
"墙贴和壁饰",
"文胸收纳包",
"骰子游戏",
"车载水杯架",
"方格置物架",
"自行车刹车片衬垫",
"地毯",
"女士空顶遮阳帽",
"杯垫、隔热垫",
"网格本与数据本",
"女士时尚手串",
"其他(卫浴毛巾)",
"车身维修凹坑清除工具",
"反光装置",
"缝纫穿线器",
"摩托车把手配件",
"户外休闲袜",
"商用食品袋封口器",
"户外筷子、刀、叉",
"其他(公用叉勺服务餐具)",
"土豆捣碎器",
"魔鬼蛋托盘",
"浴室托盘",
"战术袋",
"甜点叉",
"珠宝戒指坯与配件",
"花园微缩雕塑",
"首饰盒",
"水果和蔬菜去核机",
"虱子梳",
"裤子衣架",
"徒步旅行背包",
"壁挂酒架",
"其他(镜头配件)",
"充气设备配件",
"胡桃夹子",
"餐饮服务工具和餐具",
"巧克力模具",
"饼干模具",
"创意造型蛋糕模具",
"小动物喂食碗",
"刀盒、刀具收纳和保护器",
"配件",
"房车配件",
"装饰杆头",
"蛋糕装饰",
"派对照相亭道具",
"悬挂厨房篮",
"开瓶器",
"床单紧固件",
"游泳装备包",
"汽车遮阳板",
"玻璃杯",
"男士编织手链",
"地刮、玻璃刮板",
"女士时尚手链",
"脚垫",
"女士时尚开口手镯",
"女士脚链",
"收纳箱",
"双筒望远镜、相机、摄像机挂带及背包",
"猫抓板",
"乐谱文件夹",
"相册和相簿",
"清洁海绵",
"首饰架",
"工艺品收纳盒和整理器",
"发饰(头发装饰)",
"女士防寒连指手套",
"其他(面部护理和面膜)",
"其他(狗清洁用品)",
"浴球",
"粘土模具",
"其他(线缆管理)",
"首饰链子",
"派对头饰",
"珠饰套件",
"卫生纸架",
"吉他维修工具",
"墙贴",
"女士公交卡套",
"平板电脑贴纸",
"车用收纳",
"海绵粉扑",
"面膜"
]
File diff suppressed because it is too large. Load diff
+133
View File
@@ -0,0 +1,133 @@
{
"items": [
"* 店铺名称 [select] ①Alimingpro",
"* 产品分类 [input] ",
" 产品属性 [-] ",
" 店小秘分类 [-] ",
" 来源URL [input] ",
" [input] ",
"* 产品标题 [input] ",
" 英文标题 [input] ",
" 产品货号 [input] ",
"* 产地 [select] 中国大陆",
" 制造地点 [select] 中国大陆",
" 产地说明书 [input] ",
" 站外产品链接 [input] ",
" 敏感属性 [input] 1",
" 定制产品 [input] 1",
"* 产品轮播图 [input] on",
"* 产品素材图 [-] ",
" 产品视频 [-] ",
"* 外包装形状 [input] ",
"* 外包装类型 [input] ",
"* 外包装图片 [input] on",
" 产品说明书 [input] ",
" 描述视频 [-] ",
" 产品描述 [-] "
],
"tables": [],
"dump": {
"temuAddProductStore": {
"formState": {
"mainImage": "[]",
"videoData": {},
"productNumber": "",
"productName": "",
"productEnName": "",
"outerGoodsUrl": "",
"productOrigin": "CN",
"region2Id": "",
"region1ShortNames": "[1] \"CN\"",
"originFileUrl": "",
"checkedSensitiveList": "[]",
"sensitiveState": 0,
"batteryCapacity": "",
"maxLiquidCapacity": "",
"maxKnifeLength": "",
"knifeAngle": "",
"personalizationSwitch": 0,
"technology": 1,
"firstType": "",
"twiceType": "[]",
"invitation": {
"invitationName": "",
"siteName": "",
"id": ""
}
},
"dataState": {
"newSizeGroups": "[]",
"newBootSizeGroups": "[]"
},
"countryCode": "[282] {\"value\":\"CN\",\"label\":\"中国大陆\"}",
"regionCode": "[32] {\"value\":\"\",\"label\":\"请选择省份\"}",
"title_limit": {
"nameMin": 0,
"nameMax": 500
},
"img_limit": {
"popMinImgNum": 3,
"pddkjMinImgNum": 5,
"maxImgNum": 10
}
},
"temuAddSkuDataStore": {
"formState": {
"skuDataList": "[]",
"sitePrice": false,
"codeType": "1"
},
"dataState": {
"warehouseList": "[]",
"goodsTemplateList": "[]",
"warehouseCheckedList": "[]"
}
},
"temuAddSkuAttrStore": {
"formState": {
"skuAttrs": "[]",
"basePlateType": 0,
"sizeChartList": "[]"
},
"dataState": {
"newBootSizeGroups": "[]",
"newSizeGroups": "[]",
"customThemeOptions": "[]",
"templateList": "[]"
},
"customAttrOptions": {}
},
"temuAddBasicStore": {
"formState": {
"shopId": "4021529",
"productSemiManagedReq": "100"
},
"dataState": {
"categories": "[1038] {\"id\":4810363372086185,\"puid\":70000,\"platform\":\"pddkj\",\"site\":null,\"shopId\":4021529,\"categoryId\":\"1432\",\"num\":385,\"classType\":-1,\"createTime\":null,\"updateTime\":null,\"createId\":null,\"nameZh\":\"证件内页\",\"nameEn\":\"证件内页\",\"nodePath\":\"办公用品/日常办公用品/标签指",
"promiseTemplateList": "[]",
"freightTemplateList": "[]",
"commonHasNewBootSize": false,
"commonHasNewSize": false,
"categoryPathName": "",
"categoryPathIds": "[]"
},
"keywordShowData": {
"attrKeywords": "[]",
"hotKeywords": "[]",
"upKeywords": "[]",
"lessKeywords": "[]"
}
},
"temuAddAttrStore": {
"formState": {
"customAttrs": "[]",
"motorIds": "[]",
"motorAfid": "[]",
"templateData": "[]"
},
"dataState": {
"motorTemplate": "[]"
}
}
}
}
+80
View File
@@ -0,0 +1,80 @@
{
"stores": [
"temuCarDataStore",
"temuAddProductStore",
"temuAddStore",
"temuAddAttrStore",
"temuAddSkuDataStore",
"temuAddSkuAttrStore",
"temuAddBasicStore",
"temuAddOtherStore"
],
"items": [
"* 店铺名称 [select] ①Alimingpro",
"* 产品分类 [input] ",
" 产品属性 [-] ",
" 店小秘分类 [-] ",
" 来源URL [input] ",
" [input] ",
"* 产品标题 [input] ",
" 英文标题 [input] ",
" 产品货号 [input] ",
"* 产地 [select] 中国大陆",
" 制造地点 [select] 中国大陆",
" 产地说明书 [input] ",
" 站外产品链接 [input] ",
" 敏感属性 [input] 1",
" 定制产品 [input] 1",
"* 产品轮播图 [input] on",
"* 产品素材图 [-] ",
" 产品视频 [-] ",
"* 外包装形状 [input] ",
"* 外包装类型 [input] ",
"* 外包装图片 [input] on",
" 产品说明书 [input] ",
" 描述视频 [-] ",
" 产品描述 [-] "
],
"dump": {
"temuCarDataStore": {
"supportCarAttr": "false",
"supportCarCategory": "false",
"showBackStatus": "loadingFinish"
},
"temuAddProductStore": {
"formState.productOrigin": "CN",
"formState.sensitiveState": "0",
"formState.personalizationSwitch": "0",
"formState.technology": "1",
"title_limit.nameMin": "0",
"title_limit.nameMax": "500",
"img_limit.popMinImgNum": "3",
"img_limit.pddkjMinImgNum": "5",
"img_limit.maxImgNum": "10"
},
"temuAddStore": {
"attrsInfo.categoryType": "-1",
"attrsInfo.customThemeNum": "0",
"dataState.supportBasePlat": "false"
},
"temuAddAttrStore": {},
"temuAddSkuDataStore": {
"formState.sitePrice": "false",
"formState.codeType": "1"
},
"temuAddSkuAttrStore": {
"formState.basePlateType": "0"
},
"temuAddBasicStore": {
"formState.shopId": "4021529",
"formState.productSemiManagedReq": "100",
"dataState.commonHasNewBootSize": "false",
"dataState.commonHasNewSize": "false"
},
"temuAddOtherStore": {
"dataState.isJoinChoice": "false",
"dataState.isShowQualificationModal": "false",
"packageFormState.inventoryRegion": "1"
}
}
}
+190
View File
@@ -0,0 +1,190 @@
{
"548459586741": {
"cat": "口哨",
"catId": "18723"
},
"661190598139": {
"cat": "发圈和头绳",
"catId": "19285"
},
"764423265986": {
"cat": "口腔温度计",
"catId": "8167"
},
"685456757807": {
"cat": "编织绳",
"catId": "39534"
},
"735147938123": {
"cat": "女士发箍",
"catId": "29276"
},
"627879474686": {
"cat": "女婴袜子",
"catId": "26923"
},
"610164857063": {
"cat": "女士发箍",
"catId": "29276"
},
"676236596821": {
"cat": "发夹",
"catId": "19287"
},
"708420302844": {
"cat": "女士钥匙环、钥匙链",
"catId": "29284"
},
"866537106657": {
"cat": "纽扣",
"catId": "39592"
},
"547183997437": {
"cat": "女士时尚链式项链",
"catId": "29548"
},
"657617635303": {
"cat": "办公收纳用品",
"catId": "1239"
},
"641673262387": {
"cat": "其他(饰品收纳)",
"catId": "31137"
},
"953869908708": {
"cat": "墙贴",
"catId": "12169"
},
"703822717997": {
"cat": "办公收纳用品",
"catId": "1239"
},
"863524134410": {
"cat": "贴纸",
"catId": "39474"
},
"694637537727": {
"cat": "午餐包、午餐袋",
"catId": "10292"
},
"623011262210": {
"cat": "墙贴",
"catId": "12169"
},
"836512561982": {
"cat": "化妆包",
"catId": "19669"
},
"714492799386": {
"cat": "化妆包",
"catId": "19669"
},
"591994902720": {
"cat": "笔袋",
"catId": "40458"
},
"853414558425": {
"cat": "女士钥匙环、钥匙链",
"catId": "29284"
},
"997450831819": {
"cat": "贴纸",
"catId": "39474"
},
"639409307567": {
"cat": "墙贴",
"catId": "12169"
},
"902440558099": {
"cat": "发圈和头绳",
"catId": "19285"
},
"823838532886": {
"cat": "证件卡夹卡套",
"catId": "1431"
},
"698782391248": {
"cat": "贴纸",
"catId": "39474"
},
"707826905566": {
"cat": "女士卡包、证件包",
"catId": "29318"
},
"1027332215847": {
"cat": "首饰盒",
"catId": "12735"
},
"682195499823": {
"cat": "笔袋",
"catId": "40458"
},
"823560564174": {
"cat": "发圈和头绳",
"catId": "19285"
},
"739147684759": {
"cat": "纽扣",
"catId": "39592"
},
"621300323670": {
"cat": "办公收纳用品",
"catId": "1239"
},
"896469995553": {
"cat": "登山扣饰和钥匙扣",
"catId": "34174"
},
"944470567338": {
"cat": "发夹",
"catId": "19287"
},
"787261097583": {
"cat": "发夹",
"catId": "19287"
},
"833753630925": {
"cat": "女士发箍",
"catId": "29276"
},
"719391062058": {
"cat": "化妆品收纳盒",
"catId": "11800"
},
"857781294719": {
"cat": "发夹",
"catId": "19287"
},
"863384503032": {
"cat": "发夹",
"catId": "19287"
},
"774494945453": {
"cat": "女士钥匙环、钥匙链",
"catId": "29284"
},
"750271307455": {
"cat": "女士钥匙环、钥匙链",
"catId": "29284"
},
"726442972676": {
"cat": "发夹",
"catId": "19287"
},
"775057912118": {
"cat": "女士钥匙环、钥匙链",
"catId": "29284"
},
"893592264148": {
"cat": "发夹",
"catId": "19287"
},
"607330049419": {
"cat": "发圈和头绳",
"catId": "19285"
},
"854003999648": {
"cat": "发圈和头绳",
"catId": "19285"
}
}
+18
View File
@@ -0,0 +1,18 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
await c.evalJS(`window.scrollTo(0,document.body.scrollHeight)`); await wait(2000);
const o = await c.evalJS(`(()=>{
const items=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null).map(x=>{
const l=x.querySelector('label'); const lab=l?(l.innerText||'').replace(/\\s+/g,' ').trim():'';
const req=!!x.querySelector('.ant-form-item-required');
const inp=x.querySelector('input:not([type=hidden])'); const ta=x.querySelector('textarea'); const sel=x.querySelector('.ant-select-selection-item');
const r=x.getBoundingClientRect();
return {y:Math.round(r.y), s:(req?'* ':' ')+lab.slice(0,20)+' ['+(ta?'ta':(sel?'select':(inp?'input':'-')))+'] '+(sel?sel.innerText.trim():(inp?inp.value:(ta?ta.value:''))).slice(0,20)};
}).filter(x=>x.s.trim().length>4);
const tables=[...document.querySelectorAll('table')].filter(t=>t.offsetParent!==null).map(t=>({
th:[...t.querySelectorAll('th')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).slice(0,12),
rows:[...t.querySelectorAll('tbody tr')].filter(x=>x.querySelectorAll('input').length).length}));
return JSON.stringify({tables, low:items.filter(x=>x.y>0).slice(-14).map(x=>x.s)},null,1);})()`);
console.log(String(o).slice(0,1400));
process.exit(0);
+22
View File
@@ -0,0 +1,22 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/产品分类/.test(l.innerText||'');});
if(!it)return'nf'; return JSON.stringify({txt:(it.innerText||'').replace(/\\s+/g,' ').slice(0,120), html:it.innerHTML.slice(0,500)});})()`);
console.log('分类控件:', String(o).slice(0,700));
const pos = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/产品分类/.test(l.innerText||'');});
if(!it)return'[]'; const el=it.querySelector('.ant-select-selector')||it.querySelector('input'); if(!el)return'[]';
el.scrollIntoView({block:'center'}); const r=el.getBoundingClientRect();
return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
if(pos.length){ for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1}); await wait(4000); }
const o2 = await c.evalJS(`(()=>{
const ms=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null).map(m=>({t:(m.querySelector('.ant-modal-title')||{}).innerText||'',
inputs:[...m.querySelectorAll('input')].map(i=>i.placeholder||i.type).slice(0,5),
btns:[...m.querySelectorAll('button')].map(b=>(b.innerText||'').trim()).slice(0,6),
txt:(m.innerText||'').replace(/\\s+/g,' ').slice(0,280)}));
const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).map(d=>(d.innerText||'').replace(/\\s+/g,' ').slice(0,220));
return JSON.stringify({modals:ms, dropdowns:dd},null,1);})()`);
console.log(String(o2).slice(0,1200));
process.exit(0);
+16
View File
@@ -0,0 +1,16 @@
import { attach } from '/tmp/cdp3.mjs';
import fs from 'fs';
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const s=p._s.get('temuAddBasicStore').$state.dataState;
let cats=s.categories; if(typeof cats==='string') cats=JSON.parse(cats);
return JSON.stringify(cats.map(x=>({id:String(x.categoryId), name:x.nameZh, path:x.nodePath||''})));})()`);
const list = JSON.parse(String(o));
fs.writeFileSync('/tmp/temu_cats_full.json', JSON.stringify(list,null,1));
console.log('Temu 全量类目:', list.length);
const KEYS=['发夹','发饰','发圈','发箍','头绳','贴纸','墙贴','钥匙','笔袋','卡包','卡夹','化妆包','袜','收纳','项链','书签','纽扣','口哨','毛线','温度计','围巾'];
for(const k of KEYS){
const hits=list.filter(x=>x.name.includes(k)).slice(0,5);
if(hits.length) console.log(` [${k}] ` + hits.map(h=>h.name).join(' / '));
}
process.exit(0);
+19
View File
@@ -0,0 +1,19 @@
import { attach } from '/tmp/cdp3.mjs';
import fs from 'fs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const all = new Set();
for (let i=0;i<80;i++){
const got = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'[]'; return JSON.stringify([...dd.querySelectorAll('.ant-select-item-option')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).filter(Boolean));})()`);
const arr=JSON.parse(String(got)); const before=all.size; arr.forEach(x=>all.add(x));
const sc = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return 0; const rc=dd.querySelector('.rc-virtual-list-holder')||dd; rc.scrollTop=rc.scrollTop+600; return rc.scrollTop;})()`);
await wait(400);
if (all.size===before && i>4 && Number(sc)===0) break;
}
const list=[...all];
fs.writeFileSync('/tmp/temu_cats.json', JSON.stringify(list,null,1));
console.log('Temu 类目数:', list.length);
list.forEach((x,i)=>console.log(` ${String(i).padStart(3)} ${x}`));
process.exit(0);
+22
View File
@@ -0,0 +1,22 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
await c.evalJS(`document.body.dispatchEvent(new MouseEvent('mousedown',{bubbles:true}));document.body.click();`);
await wait(1200);
const pos = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/产品分类/.test(l.innerText||'');});
const el=it.querySelector('.ant-select-selector'); el.scrollIntoView({block:'center'});
const r=el.getBoundingClientRect(); return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
console.log('坐标:', JSON.stringify(pos));
for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1});
await wait(3500);
const o = await c.evalJS(`(()=>{
const dds=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null);
if(!dds.length) return 'no-dd';
const dd=dds[dds.length-1];
const opts=[...dd.querySelectorAll('.ant-select-item-option')];
const anyItems=[...dd.querySelectorAll('[class*=item]')].slice(0,5).map(e=>String(e.className).slice(0,40));
return JSON.stringify({n:opts.length, first:opts.slice(0,4).map(e=>JSON.stringify(e.innerText)), anyItems,
txt:(dd.innerText||'').replace(/\\s+/g,' ').slice(0,200)});})()`);
console.log('下拉:', String(o).slice(0,800));
process.exit(0);
+35
View File
@@ -0,0 +1,35 @@
import { attach } from '/tmp/cdp3.mjs';
import fs from 'fs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const CAT='发饰(头发装饰)';
// 选类目
const pk = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; const hit=[...dd.querySelectorAll('.ant-select-item-option')].find(o=>(o.innerText||'').trim()===${JSON.stringify(CAT)});
if(!hit)return'no-hit'; for(const ev of ['mousedown','mouseup','click']) hit.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));
return 'picked';})()`);
console.log('类目:', pk);
await wait(12000);
const o = await c.evalJS(`(()=>{
const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const items=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null).map(x=>{
const l=x.querySelector('label'); const lab=l?(l.innerText||'').replace(/\\s+/g,' ').trim():'';
const req=!!x.querySelector('.ant-form-item-required');
const inp=x.querySelector('input:not([type=hidden])'); const ta=x.querySelector('textarea'); const sel=x.querySelector('.ant-select-selection-item');
return (req?'* ':' ')+lab.slice(0,22).padEnd(23)+'['+(ta?'ta':(sel?'select':(inp?'input':'-')))+'] '+(sel?sel.innerText.trim():(inp?inp.value:(ta?ta.value:''))).slice(0,22);
}).filter(x=>x.trim().length>4);
const tables=[...document.querySelectorAll('table')].filter(t=>t.offsetParent!==null).map(t=>({
th:[...t.querySelectorAll('th')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).slice(0,12),
rows:[...t.querySelectorAll('tbody tr')].filter(x=>x.querySelectorAll('input').length).length}));
const cut=(x,d=0)=>(d>3?'…':(Array.isArray(x)?(x.length?'['+x.length+'] '+JSON.stringify(x[0]).slice(0,240):'[]'):(x&&typeof x==='object'?Object.fromEntries(Object.entries(x).map(([k,v])=>[k,cut(v,d+1)])):x)));
const dump={};
for(const n of ['temuAddProductStore','temuAddSkuDataStore','temuAddSkuAttrStore','temuAddBasicStore','temuAddAttrStore'])
{ try{dump[n]=cut(JSON.parse(JSON.stringify(p._s.get(n).$state)));}catch(e){dump[n]='ERR';} }
return JSON.stringify({items, tables, dump},null,1);})()`);
fs.writeFileSync('/tmp/temu_deep.json', String(o));
const j=JSON.parse(String(o));
console.log('=== form ==='); j.items.forEach(x=>console.log(' '+x));
console.log('=== tables ==='); console.log(JSON.stringify(j.tables));
console.log('=== stores ===');
for(const [n,v] of Object.entries(j.dump)) console.log(' ##',n,JSON.stringify(v).slice(0,560));
process.exit(0);
+55
View File
@@ -0,0 +1,55 @@
import { attach } from '/tmp/cdp3.mjs';
import fs from 'fs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const CAT=process.argv[2]||'发夹';
await c.evalJS(`document.body.dispatchEvent(new MouseEvent('mousedown',{bubbles:true}));document.body.click();`);
await wait(1200);
const pos = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/产品分类/.test(l.innerText||'');});
const el=it.querySelector('.ant-select-selector'); el.scrollIntoView({block:'center'});
const r=el.getBoundingClientRect(); return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1});
await wait(3000);
let res='nf';
for(let i=0;i<90;i++){
const r = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; const target=${JSON.stringify(CAT)};
const hit=[...dd.querySelectorAll('.ant-select-item-option')].find(o=>(o.innerText||'').trim()===target);
if(!hit)return'scroll';
for(const ev of ['mousedown','mouseup','click']) hit.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));
return 'picked';})()`);
if(r==='picked'){res='picked';break;}
if(r==='no-dd'){res='no-dd';break;}
await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return 0; const rc=dd.querySelector('.rc-virtual-list-holder')||dd; rc.scrollTop=rc.scrollTop+500; return rc.scrollTop;})()`);
await wait(280);
}
console.log('类目:', res, CAT);
if(res!=='picked') process.exit(1);
await wait(14000);
const o = await c.evalJS(`(()=>{
const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const items=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null).map(x=>{
const l=x.querySelector('label'); const lab=l?(l.innerText||'').replace(/\\s+/g,' ').trim():'';
const req=!!x.querySelector('.ant-form-item-required');
const inp=x.querySelector('input:not([type=hidden])'); const ta=x.querySelector('textarea'); const sel=x.querySelector('.ant-select-selection-item');
return (req?'* ':' ')+lab.slice(0,22).padEnd(23)+'['+(ta?'ta':(sel?'select':(inp?'input':'-')))+'] '+(sel?sel.innerText.trim():(inp?inp.value:(ta?ta.value:''))).slice(0,22);
}).filter(x=>x.trim().length>4);
const tables=[...document.querySelectorAll('table')].filter(t=>t.offsetParent!==null).map(t=>({
th:[...t.querySelectorAll('th')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).slice(0,12),
rows:[...t.querySelectorAll('tbody tr')].filter(x=>x.querySelectorAll('input').length).length}));
const cut=(x,d=0)=>(d>3?'…':(Array.isArray(x)?(x.length?'['+x.length+'] '+JSON.stringify(x[0]).slice(0,260):'[]'):(x&&typeof x==='object'?Object.fromEntries(Object.entries(x).map(([k,v])=>[k,cut(v,d+1)])):x)));
const dump={};
for(const n of ['temuAddProductStore','temuAddSkuDataStore','temuAddSkuAttrStore','temuAddBasicStore','temuAddAttrStore'])
{ try{dump[n]=cut(JSON.parse(JSON.stringify(p._s.get(n).$state)));}catch(e){dump[n]='ERR';} }
const b=p._s.get('temuAddBasicStore').$state;
return JSON.stringify({items, tables, dump, catId:b.formState.categoryId, path:b.dataState.categoryPathName},null,1);})()`);
fs.writeFileSync('/tmp/temu_deep.json', String(o));
const j=JSON.parse(String(o));
console.log('catId:', j.catId, '| path:', j.path);
console.log('=== form ==='); j.items.forEach(x=>console.log(' '+x));
console.log('=== tables ==='); console.log(JSON.stringify(j.tables));
console.log('=== stores ===');
for(const [n,v] of Object.entries(j.dump)) console.log(' ##',n,JSON.stringify(v).slice(0,520));
process.exit(0);
+52
View File
@@ -0,0 +1,52 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const reqs=[];
c.on(m=>{ if(m.method==='Network.requestWillBeSent'){const r=m.params.request;
if(/temu/i.test(r.url)&&/\.json/.test(r.url)&&r.method==='POST') reqs.push(r.url.replace('https://www.dianxiaomi.com','')); }});
await c.send('Network.enable').catch(()=>{});
const IMGS=['https://cbu01.alicdn.com/img/ibank/O1CN01IHtNAHKMzNC1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01UGEWafTzqTH1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01d0hA4N72jzD1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01edgGxIlmdtJ1chua_!!2222444614399-0-cib.jpg'];
const r = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const f=p._s.get('temuAddProductStore').$state.formState;
const imgs=${JSON.stringify(IMGS)};
// 试探 mainImage 形状
if(Array.isArray(f.mainImage)) f.mainImage=imgs.map((u,i)=>({url:u,imgUrl:u,name:'img'+(i+1)+'.jpg',width:800,height:800}));
else f.mainImage=JSON.stringify(imgs.map((u,i)=>({url:u,imgUrl:u,name:'img'+(i+1)+'.jpg',width:800,height:800})));
f.productName='Hair Clips Set for Women Girls Fashion Hair Accessories';
const a=p._s.get('temuAddSkuAttrStore').$state.formState;
if(a.skuAttrs&&a.skuAttrs[0]) a.skuAttrs[0].options=[{optionName:'Black',name:'Black',value:'Black',optionId:1}];
return JSON.stringify({imgIsArray:Array.isArray(${JSON.stringify(IMGS)}), mainImgType:Array.isArray(f.mainImage)?'array':typeof f.mainImage,
n:Array.isArray(f.mainImage)?f.mainImage.length:'?', opts:a.skuAttrs&&a.skuAttrs[0]?a.skuAttrs[0].options.length:0});})()`);
console.log('填充:', r);
await wait(3500);
// 找外包装形状并选“长方体”
await c.evalJS(`document.body.click()`); await wait(600);
const pos = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/外包装形状/.test(l.innerText||'');});
if(!it)return'[]'; const s=it.querySelector('.ant-select-selector'); if(!s)return'[]';
s.scrollIntoView({block:'center'}); const r=s.getBoundingClientRect();
return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
if(pos.length){ for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1}); await wait(2500); }
const pk = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; const hit=[...dd.querySelectorAll('.ant-select-item-option')].find(o=>/长方体/.test(o.innerText||''));
if(!hit)return'no-hit'; for(const ev of ['mousedown','mouseup','click']) hit.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 'picked';})()`);
console.log('外包装形状:', pk);
await wait(2000);
// 保存并抓错误
await c.evalJS(`window.scrollTo(0,0)`); await wait(600);
await c.evalJS(`(()=>{const x=[...document.querySelectorAll('button')].filter(e=>e.offsetParent!==null).find(e=>/^\\s*保存\\s*$/.test((e.innerText||'').trim()));
if(x) for(const ev of ['mousedown','mouseup','click']) x.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 1;})()`);
await wait(10000);
const err = await c.evalJS(`(()=>{const ex=[...document.querySelectorAll('.ant-form-item-explain-error')].map(e=>(e.innerText||'').trim()).filter(Boolean);
const red=[]; document.querySelectorAll('*').forEach(el=>{ if(el.offsetParent===null||el.children.length)return;
const t=(el.innerText||'').trim(); if(!t||t.length>60)return;
const s=getComputedStyle(el); const m=(s.color||'').match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/); if(!m)return;
if(+m[1]>160&&+m[2]<140&&+m[3]<140) red.push(t); });
const toasts=[...document.querySelectorAll('.ant-message-notice,.ant-notification-notice')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).filter(Boolean);
return JSON.stringify({ex:[...new Set(ex)].slice(0,12), red:[...new Set(red)].slice(0,14), toasts:[...new Set(toasts)].slice(0,3)});})()`);
console.log('校验:', String(err).slice(0,1000));
console.log('POST:', JSON.stringify([...new Set(reqs)].slice(0,4)));
process.exit(0);
+19
View File
@@ -0,0 +1,19 @@
import { attach } from '/tmp/cdp3.mjs';
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const out={};
for(const n of [...p._s.keys()].filter(k=>/temu/i.test(k))){
const s=p._s.get(n).$state; const ks=[];
const walk=(x,path,d)=>{ if(d>2||!x||typeof x!=='object')return;
if(Array.isArray(x)) return;
for(const k of Object.keys(x)){ if(/img|image|pic|photo|material/i.test(k)) ks.push(path+'.'+k+'='+JSON.stringify(x[k]).slice(0,40));
else walk(x[k],path+'.'+k,d+1); } };
walk(s,n,0); if(ks.length) out[n]=ks.slice(0,8);
}
// 外包装类型 是不是 input
const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/外包装类型/.test(l.innerText||'');});
const info=it?{html:it.innerHTML.slice(0,360)}:{};
return JSON.stringify({out, info},null,1);})()`);
console.log(String(o).slice(0,1800));
process.exit(0);
+52
View File
@@ -0,0 +1,52 @@
import { newTarget, CDP } from '/tmp/cdp3.mjs';
import fs from 'fs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const SHOP='①Alimingpro';
const tl = await (await fetch('http://127.0.0.1:9223/json/list')).json();
for (const x of tl.filter(y=>y.type==='page'&&/temu/i.test(y.url))) await fetch(`http://127.0.0.1:9223/json/close/${x.id}`).catch(()=>{});
await wait(900);
const nt = await newTarget('about:blank');
const c = await CDP.connect(nt.webSocketDebuggerUrl);
await c.send('Page.enable'); await c.send('Runtime.enable');
await c.send('Page.navigate',{url:'https://www.dianxiaomi.com/web/temu/add'});
await wait(22000);
console.log('url:', await c.evalJS('location.href'));
// 店铺选择器
const sp = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/店铺/.test(l.innerText||'');});
const s=(it||document).querySelector('.ant-select-selector')||[...document.querySelectorAll('.ant-select-selector')].filter(e=>e.offsetParent!==null)[0];
if(!s)return'[]'; s.scrollIntoView({block:'center'}); const r=s.getBoundingClientRect();
return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:sp[0],y:sp[1],button:'left',clickCount:1});
await wait(2500);
const pk = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; const hit=[...dd.querySelectorAll('.ant-select-item-option')].find(o=>(o.innerText||'').trim()===${JSON.stringify(SHOP)});
if(!hit)return'no-hit:'+[...dd.querySelectorAll('.ant-select-item-option')].slice(0,4).map(o=>o.innerText.trim()).join(',');
for(const ev of ['mousedown','mouseup','click']) hit.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 'ok';})()`);
console.log('选店铺:', pk);
await wait(9000);
const o = await c.evalJS(`(()=>{
const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const stores=[...p._s.keys()].filter(k=>/temu|pddkj/i.test(k));
const items=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null).map(x=>{
const l=x.querySelector('label'); const lab=l?(l.innerText||'').replace(/\\s+/g,' ').trim():'';
const req=!!x.querySelector('.ant-form-item-required');
const inp=x.querySelector('input:not([type=hidden])'); const ta=x.querySelector('textarea'); const sel=x.querySelector('.ant-select-selection-item');
return (req?'* ':' ')+lab.slice(0,24).padEnd(25)+'['+(ta?'ta':(sel?'select':(inp?'input':'-')))+'] '+(sel?sel.innerText.trim():(inp?inp.value:(ta?ta.value:''))).slice(0,24);
}).filter(x=>x.trim().length>4);
const dump={};
for(const n of stores){ try{ const s=p._s.get(n).$state; const o2={};
for(const k of Object.keys(s)){ const v=s[k];
if(v===null||['string','number','boolean'].includes(typeof v)){ if(v!==''&&v!==null&&String(v).length<60) o2[k]=String(v); }
else if(v&&typeof v==='object'&&!Array.isArray(v)){ for(const k2 of Object.keys(v)){ const v2=v[k2];
if(v2===null||['string','number','boolean'].includes(typeof v2)){ if(v2!==''&&v2!==null&&String(v2).length<50) o2[k+'.'+k2]=String(v2); } } } }
dump[n]=o2; }catch(e){ dump[n]='ERR'; } }
return JSON.stringify({stores, items, dump},null,1);})()`);
fs.writeFileSync('/tmp/temu_map.json', String(o));
const j=JSON.parse(String(o));
console.log('stores:', j.stores.join(', '));
console.log('--- form ---'); j.items.forEach(x=>console.log(' '+x));
console.log('--- store 关键字段 ---');
for(const [n,v] of Object.entries(j.dump)){ const hit=Object.entries(v||{}).filter(([k])=>/shop|site|currency|cat|brand|price|weight/i.test(k));
if(hit.length) console.log(' ##',n,hit.map(([k,val])=>k+'='+val).join(' | ').slice(0,300)); }
process.exit(0);
+49
View File
@@ -0,0 +1,49 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const CAT = process.argv[2] || '发夹';
const dd = () => `[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop()`;
// 滚回顶部
await c.evalJS(`(()=>{const d=${dd()}; if(!d)return 0; const rc=d.querySelector('.rc-virtual-list-holder')||d; rc.scrollTop=0; return rc.scrollTop;})()`);
await wait(1200);
let res='nf';
for(let i=0;i<120;i++){
const r = await c.evalJS(`(()=>{const d=${dd()}; if(!d)return'no-dd';
const target=${JSON.stringify(CAT)};
const hit=[...d.querySelectorAll('.ant-select-item-option')].find(o=>(o.innerText||'').trim()===target);
if(!hit)return'scroll';
for(const ev of ['mousedown','mouseup','click']) hit.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));
return 'picked';})()`);
if(r==='picked'){res='picked';break;}
if(r==='no-dd'){res='no-dd';break;}
await c.evalJS(`(()=>{const d=${dd()}; if(!d)return 0; const rc=d.querySelector('.rc-virtual-list-holder')||d; rc.scrollTop=rc.scrollTop+400; return rc.scrollTop;})()`);
await wait(230);
}
console.log('类目:', res, CAT);
if(res!=='picked') process.exit(1);
await wait(14000);
const o = await c.evalJS(`(()=>{
const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const items=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null).map(x=>{
const l=x.querySelector('label'); const lab=l?(l.innerText||'').replace(/\\s+/g,' ').trim():'';
const req=!!x.querySelector('.ant-form-item-required');
const inp=x.querySelector('input:not([type=hidden])'); const ta=x.querySelector('textarea'); const sel=x.querySelector('.ant-select-selection-item');
return (req?'* ':' ')+lab.slice(0,22).padEnd(23)+'['+(ta?'ta':(sel?'select':(inp?'input':'-')))+'] '+(sel?sel.innerText.trim():(inp?inp.value:(ta?ta.value:''))).slice(0,22);
}).filter(x=>x.trim().length>4);
const tables=[...document.querySelectorAll('table')].filter(t=>t.offsetParent!==null).map(t=>({
th:[...t.querySelectorAll('th')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).slice(0,12),
rows:[...t.querySelectorAll('tbody tr')].filter(x=>x.querySelectorAll('input').length).length}));
const cut=(x,d=0)=>(d>3?'…':(Array.isArray(x)?(x.length?'['+x.length+'] '+JSON.stringify(x[0]).slice(0,260):'[]'):(x&&typeof x==='object'?Object.fromEntries(Object.entries(x).map(([k,v])=>[k,cut(v,d+1)])):x)));
const dump={};
for(const n of ['temuAddProductStore','temuAddSkuDataStore','temuAddSkuAttrStore','temuAddBasicStore','temuAddAttrStore'])
{ try{dump[n]=cut(JSON.parse(JSON.stringify(p._s.get(n).$state)));}catch(e){dump[n]='ERR';} }
const b=p._s.get('temuAddBasicStore').$state;
return JSON.stringify({items, tables, dump, catId:b.formState.categoryId, path:b.dataState.categoryPathName},null,1);})()`);
import('fs').then(fs=>fs.writeFileSync('/tmp/temu_deep.json', String(o)));
const j=JSON.parse(String(o));
console.log('catId:', j.catId, '| path:', j.path);
console.log('=== form ==='); j.items.forEach(x=>console.log(' '+x));
console.log('=== tables ==='); console.log(JSON.stringify(j.tables));
console.log('=== stores ===');
for(const [n,v] of Object.entries(j.dump)) console.log(' ##',n,JSON.stringify(v).slice(0,500));
process.exit(0);
+30
View File
@@ -0,0 +1,30 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
await c.evalJS(`document.body.click()`); await wait(700);
const pos = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&/外包装类型/.test(l.innerText||'');});
if(!it)return'[]'; const s=it.querySelector('.ant-select-selector'); if(!s)return'[]';
s.scrollIntoView({block:'center'}); const r=s.getBoundingClientRect();
return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
console.log('坐标:', JSON.stringify(pos));
for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1});
await wait(3000);
const o = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; return JSON.stringify([...dd.querySelectorAll('.ant-select-item-option')].map(e=>(e.innerText||'').trim()).slice(0,10));})()`);
console.log('外包装类型选项:', String(o).slice(0,400));
const pk = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; const its=[...dd.querySelectorAll('.ant-select-item-option')]; if(!its.length)return'no-opt';
const hit=its.find(o=>/袋|Box|盒|Bag/i.test(o.innerText||''))||its[0];
for(const ev of ['mousedown','mouseup','click']) hit.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));
return 'picked:'+(hit.innerText||'').trim();})()`);
console.log('选择:', pk);
await wait(2000);
// 素材图 形状
const o2 = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const f=p._s.get('temuAddProductStore').$state.formState;
return JSON.stringify({matType:Array.isArray(f.materialImage)?'array':typeof f.materialImage,
mat:String(JSON.stringify(f.materialImage)).slice(0,220), mainN:Array.isArray(f.mainImage)?f.mainImage.length:'?',
pkg:(()=>{const q=p._s.get('temuAddOtherStore').$state; return JSON.stringify(q.packageFormState).slice(0,200);})()});})()`);
console.log('字段形状:', String(o2).slice(0,600));
process.exit(0);
+13
View File
@@ -0,0 +1,13 @@
import { attach } from '/tmp/cdp3.mjs';
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{
const req=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null&&e.querySelector('.ant-form-item-required'));
const empty=[], filled=[];
req.forEach(x=>{ const l=x.querySelector('label'); const lab=l?(l.innerText||'').replace(/\\s+/g,' ').trim():'';
const inp=x.querySelector('input:not([type=hidden])'); const ta=x.querySelector('textarea'); const sel=x.querySelector('.ant-select-selection-item');
const v=sel?sel.innerText.trim():(inp?inp.value:(ta?ta.value:''));
(v?filled:empty).push(lab+' ['+(ta?'ta':(sel?'select':(inp?'input':'-')))+']='+String(v).slice(0,16)); });
const expl=[...document.querySelectorAll('.ant-form-item-explain-error')].map(e=>(e.innerText||'').trim()).filter(Boolean);
return JSON.stringify({empty, filled, expl:[...new Set(expl)].slice(0,10)},null,1);})()`);
console.log(String(o).slice(0,1600));
process.exit(0);
+38
View File
@@ -0,0 +1,38 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const reqs=[];
c.on(m=>{ if(m.method==='Network.requestWillBeSent'){const r=m.params.request;
if(/temu/i.test(r.url)&&/\.json/.test(r.url)&&r.method==='POST') reqs.push(r.url.replace('https://www.dianxiaomi.com','')); }});
await c.send('Network.enable').catch(()=>{});
const IMGS=['https://cbu01.alicdn.com/img/ibank/O1CN01IHtNAHKMzNC1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01UGEWafTzqTH1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01d0hA4N72jzD1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01edgGxIlmdtJ1chua_!!2222444614399-0-cib.jpg',
'https://cbu01.alicdn.com/img/ibank/O1CN01wCkR921xkoEgfOWb0_!!2222444614399-0-cib.jpg'];
const r = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const f=p._s.get('temuAddProductStore').$state.formState;
const imgs=${JSON.stringify(IMGS)};
const mk=(u,i)=>({url:u,imgUrl:u,name:'img'+(i+1)+'.jpg',width:800,height:800});
if(Array.isArray(f.mainImage)) f.mainImage=imgs.map(mk); else f.mainImage=JSON.stringify(imgs.map(mk));
f.materialImage=imgs.slice(0,3).map(mk);
const q=p._s.get('temuAddOtherStore').$state;
if(q.packageFormState){ q.packageFormState.packageImages=imgs.slice(0,3).map(mk); q.packageFormState.packageShape=1; q.packageFormState.packageType=0; }
return JSON.stringify({main:Array.isArray(f.mainImage)?f.mainImage.length:'str', mat:Array.isArray(f.materialImage)?f.materialImage.length:'obj',
pkg:(q.packageFormState?q.packageFormState.packageImages.length:'-')});})()`);
console.log('填充:', r);
await wait(3500);
await c.evalJS(`window.scrollTo(0,0)`); await wait(600);
await c.evalJS(`(()=>{const x=[...document.querySelectorAll('button')].filter(e=>e.offsetParent!==null).find(e=>/^\\s*保存\\s*$/.test((e.innerText||'').trim()));
if(x) for(const ev of ['mousedown','mouseup','click']) x.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 1;})()`);
await wait(11000);
const err = await c.evalJS(`(()=>{const ex=[...document.querySelectorAll('.ant-form-item-explain-error')].map(e=>(e.innerText||'').trim()).filter(Boolean);
const red=[]; document.querySelectorAll('*').forEach(el=>{ if(el.offsetParent===null||el.children.length)return;
const t=(el.innerText||'').trim(); if(!t||t.length>60)return;
const s=getComputedStyle(el); const m=(s.color||'').match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/); if(!m)return;
if(+m[1]>160&&+m[2]<140&&+m[3]<140) red.push(t); });
const toasts=[...document.querySelectorAll('.ant-message-notice,.ant-notification-notice,.ant-modal')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).filter(Boolean);
return JSON.stringify({ex:[...new Set(ex)].slice(0,10), red:[...new Set(red)].slice(0,12), toasts:[...new Set(toasts)].slice(0,2)});})()`);
console.log('校验:', String(err).slice(0,800));
console.log('POST:', JSON.stringify([...new Set(reqs)].slice(0,4)));
process.exit(0);
+20
View File
@@ -0,0 +1,20 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
await c.evalJS(`document.body.click()`); await wait(600);
const pos = JSON.parse(String(await c.evalJS(`(()=>{
const boxes=[...document.querySelectorAll('*')].filter(e=>e.offsetParent!==null&&/颜色/.test(e.innerText||'')&&e.querySelector('input[type=search]')&&e.querySelectorAll('*').length<300);
const box=boxes[boxes.length-1]; if(!box)return'[]';
const s=box.closest('.ant-select')||box.querySelector('.ant-select')||box;
const sel=s.querySelector('.ant-select-selector')||s;
sel.scrollIntoView({block:'center'}); const r=sel.getBoundingClientRect();
return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
console.log('坐标:', JSON.stringify(pos));
if(pos.length){ for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1}); }
await wait(3000);
const o = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd';
const opts=[...dd.querySelectorAll('.ant-select-item-option')].map(e=>(e.innerText||'').trim());
return JSON.stringify({n:opts.length, first:opts.slice(0,10), txt:(dd.innerText||'').replace(/\\s+/g,' ').slice(0,180)});})()`);
console.log('下拉:', String(o).slice(0,600));
process.exit(0);
+12
View File
@@ -0,0 +1,12 @@
import { attach } from '/tmp/cdp3.mjs';
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const d=JSON.parse(JSON.stringify(p._s.get('temuAddSkuDataStore').$state));
const a=JSON.parse(JSON.stringify(p._s.get('temuAddSkuAttrStore').$state));
const tables=[...document.querySelectorAll('table')].filter(t=>t.offsetParent!==null).map(t=>({
th:[...t.querySelectorAll('th')].map(e=>(e.innerText||'').replace(/\\s+/g,' ').trim()).slice(0,12),
rows:[...t.querySelectorAll('tbody tr')].filter(x=>x.querySelectorAll('input').length).length}));
return JSON.stringify({tables, skuN:(d.formState.skuDataList||[]).length, row0:(d.formState.skuDataList||[])[0],
attrs:(a.formState.skuAttrs||[]).map(x=>({name:x.parentSpecName, n:(x.options||[]).length}))},null,1);})()`);
console.log(String(o).slice(0,1400));
process.exit(0);
+39
View File
@@ -0,0 +1,39 @@
import { attach } from '/tmp/cdp3.mjs';
const wait = ms => new Promise(z => setTimeout(z, ms));
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
// 1. 主规格/变种区结构
const o1 = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const a=JSON.parse(JSON.stringify(p._s.get('temuAddSkuAttrStore').$state));
const at=(a.formState.skuAttrs||[])[0]||{};
return JSON.stringify({attrKeys:Object.keys(at), attr:{type:at.type,parentSpecId:at.parentSpecId,parentSpecName:at.parentSpecName,
optCount:(at.options||[]).length, opt0:(at.options||[])[0], vals:at.values||at.checked||null},
customs:(a.dataState.customThemeOptions||[]).slice(0,2)});})()`);
console.log('变种属性:', String(o1).slice(0,900));
// 2. 页面里变种可点元素
const o2 = await c.evalJS(`(()=>{const boxes=[...document.querySelectorAll('*')].filter(e=>e.offsetParent!==null&&/颜色|Color/.test(e.innerText||'')&&e.querySelectorAll('*').length<200);
const box=boxes[boxes.length-1]; if(!box)return'nf';
const opts=[...box.querySelectorAll('.ant-tag,.ant-checkbox-wrapper,[class*=option],[class*=spec]')].filter(e=>e.offsetParent!==null).slice(0,8)
.map(e=>({tag:e.tagName,cls:String(e.className||'').slice(0,45),t:(e.innerText||'').trim().slice(0,14)}));
const inputs=[...box.querySelectorAll('input')].slice(0,4).map(i=>({ph:i.placeholder||'',cls:String(i.className||'').slice(0,40)}));
return JSON.stringify({opts, inputs});})()`);
console.log('变种区:', String(o2).slice(0,800));
// 3. 外包装形状/类型 的选项
await c.evalJS(`document.body.click()`); await wait(700);
for (const lab of ['外包装形状','外包装类型']) {
const pos = JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null)
.find(x=>{const l=x.querySelector('label'); return l&&new RegExp(${JSON.stringify(lab)}).test(l.innerText||'');});
if(!it)return'[]'; const s=it.querySelector('.ant-select-selector'); if(!s)return'[]';
s.scrollIntoView({block:'center'}); const r=s.getBoundingClientRect();
return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
if(pos.length){ for(const t of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type:t,x:pos[0],y:pos[1],button:'left',clickCount:1}); await wait(2500); }
const o = await c.evalJS(`(()=>{const dd=[...document.querySelectorAll('.ant-select-dropdown')].filter(e=>e.offsetParent!==null).pop();
if(!dd)return'no-dd'; return JSON.stringify([...dd.querySelectorAll('.ant-select-item-option')].map(e=>(e.innerText||'').trim()).slice(0,12));})()`);
console.log(lab+':', String(o).slice(0,300));
await c.evalJS(`document.body.click()`); await wait(700);
}
// 4. 图片字段类型
const o4 = await c.evalJS(`(()=>{const p=document.querySelector('#app').__vue_app__.config.globalProperties.$pinia;
const f=p._s.get('temuAddProductStore').$state.formState;
return JSON.stringify({mainImageType:typeof f.mainImage, mainImage:String(f.mainImage).slice(0,60)});})()`);
console.log('图片字段:', String(o4).slice(0,300));
process.exit(0);
+11
View File
@@ -0,0 +1,11 @@
import { attach } from '/tmp/cdp3.mjs';
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{
const boxes=[...document.querySelectorAll('*')].filter(e=>e.offsetParent!==null&&/颜色/.test(e.innerText||'')&&e.querySelectorAll('input').length>0&&e.querySelectorAll('*').length<300);
const box=boxes[boxes.length-1]; if(!box)return'nf';
const ins=[...box.querySelectorAll('input')].map(i=>({ph:i.placeholder||'',type:i.type,cls:String(i.className||'').slice(0,45)}));
const btns=[...box.querySelectorAll('button,a,span')].filter(e=>e.offsetParent!==null&&(e.innerText||'').trim()).slice(0,10).map(e=>({tag:e.tagName,t:(e.innerText||'').trim().slice(0,14)}));
return JSON.stringify({txt:(box.innerText||'').replace(/\\s+/g,' ').slice(0,260), ins, btns,
html:box.innerHTML.slice(0,400)},null,1);})()`);
console.log(String(o).slice(0,1500));
process.exit(0);
+11
View File
@@ -0,0 +1,11 @@
import { attach } from '/tmp/cdp3.mjs';
const c = await attach('/web/temu/add') || await attach('dianxiaomi.com');
const o = await c.evalJS(`(()=>{
// 找含“颜色”且含“添加/请选择”的容器
const cands=[...document.querySelectorAll('div')].filter(e=>e.offsetParent!==null&&/颜色/.test(e.innerText||'')&&e.querySelectorAll('input').length>=1&&e.querySelectorAll('*').length<400);
const box=cands[cands.length-1]; if(!box)return'nf';
const ins=[...box.querySelectorAll('input')].filter(i=>i.offsetParent!==null).map(i=>({type:i.type,ph:i.placeholder||'',cls:String(i.className||'').slice(0,50),dis:i.disabled}));
const btns=[...box.querySelectorAll('button')].filter(e=>e.offsetParent!==null).map(b=>({t:(b.innerText||'').trim().slice(0,12),dis:b.disabled,cls:String(b.className||'').slice(0,40)}));
return JSON.stringify({n:cands.length, txt:(box.innerText||'').replace(/\\s+/g,' ').slice(0,320), ins, btns},null,1);})()`);
console.log(String(o).slice(0,1500));
process.exit(0);