引言
很多做电商的朋友在问:"有没有能自动分类颜色图的工具?""SKU图片怎么按颜色/尺码自动命名?"
做服装、鞋包类目的电商运营都知道,一个商品通常有多个颜色和尺码,每个规格对应独立的SKU图片。手动下载后,所有图片混在一起,文件名是乱码,完全分不清哪个颜色对应哪张图。每个商品要花5-10分钟手动筛选。
本文从技术角度深度解析SKU图的自动识别与分类技术,包括DOM容器定位、属性名称提取、图片关联等核心模块。类似的技术方案在一键存图中已有成熟应用。
一、SKU图的结构特征
1.1 什么是SKU图?
SKU(Stock Keeping Unit,库存单位)图是指商品不同规格对应的细节图片。例如:
-
颜色规格:红色款细节图、蓝色款细节图、黑色款细节图
-
尺码规格:S码细节图、M码细节图、L码细节图
-
型号规格:标准版细节图、Pro版细节图
1.2 SKU图的DOM结构
各电商平台的SKU容器结构虽有差异,但模式相似:
html
<!-- 淘宝SKU容器 -->
<div class="tb-sku">
<div class="sku-item" data-value="红色">
<img src="red_thumb.jpg">
<span class="sku-name">红色</span>
</div>
<div class="sku-item" data-value="蓝色">
<img src="blue_thumb.jpg">
<span class="sku-name">蓝色</span>
</div>
</div>
<!-- 京东SKU容器 -->
<div class="sku-img-list">
<div class="sku-img-item" title="红色">
<img src="red_thumb.jpg">
<span class="sku-name">红色</span>
</div>
</div>
<!-- 拼多多SKU容器 -->
<div class="sku-list">
<div class="sku-item" data-value="红色">
<img src="red_thumb.jpg">
<span class="sku-name">红色</span>
</div>
</div>
二、SKU容器定位
不同平台的SKU容器使用不同的CSS类名,需要使用多选择器策略:
javascript
function findSkuContainer() {
const selectors = [
// 淘宝/天猫
'.tb-sku',
'.J_sku',
// 京东
'.sku-img-list',
'.J_skuImgList',
// 拼多多
'.sku-list',
'.J_skuList',
// 1688
'.sku-list',
'.J_skuList',
'.attribute-list',
// 通用
'.sku',
'[class*="sku"]',
'[class*="attribute"]'
];
for (const selector of selectors) {
const container = document.querySelector(selector);
if (container && container.querySelectorAll('img').length > 0) {
return container;
}
}
return null;
}
三、SKU项解析
3.1 SKU项遍历
找到SKU容器后,需要遍历其中的每个SKU项:
javascript
function extractSkuItems(container) {
const skuItems = [];
const itemSelectors = [
'.sku-item',
'.J_skuItem',
'.sku-img-item',
'.attribute-item',
'[data-value]'
];
let items = [];
for (const selector of itemSelectors) {
items = container.querySelectorAll(selector);
if (items.length > 0) break;
}
for (const item of items) {
const skuData = parseSkuItem(item);
if (skuData) {
skuItems.push(skuData);
}
}
return skuItems;
}
3.2 属性名称提取(多级降级策略)
属性名称(颜色、尺码等)可能存在于多个位置,需要多级降级提取:
javascript
function extractSkuName(item) {
// 第一优先级:专门的名称元素
const nameSelectors = [
'.sku-name',
'.J_skuName',
'.tb-sku-name',
'.attr-name',
'.property-name'
];
for (const selector of nameSelectors) {
const nameEl = item.querySelector(selector);
if (nameEl) {
const name = nameEl.textContent?.trim();
if (name && name.length > 0 && name.length < 30) {
return name;
}
}
}
// 第二优先级:data属性
const dataValue = item.getAttribute('data-value');
if (dataValue && dataValue.length < 30) {
return dataValue;
}
const dataTitle = item.getAttribute('data-title');
if (dataTitle && dataTitle.length < 30) {
return dataTitle;
}
// 第三优先级:title属性
const title = item.getAttribute('title');
if (title && title.length < 30) {
return title;
}
// 第四优先级:内部文本(去除多余空白)
const text = item.textContent?.trim();
if (text && text.length > 0 && text.length < 20) {
return text;
}
return null;
}
3.3 SKU图片提取
javascript
function extractSkuImage(item) {
const img = item.querySelector('img');
if (!img) return null;
let url = img.src || img.getAttribute('data-src') || img.getAttribute('data-original');
if (!url) return null;
// 转换为原图URL
url = url.split('?')[0];
url = url.replace(/_\d+x\d+\./g, '.');
return url;
}
3.4 完整SKU项解析
javascript
function parseSkuItem(item) {
const name = extractSkuName(item);
const url = extractSkuImage(item);
// 必须有名称或图片才保留
if (!name && !url) return null;
return {
name: name || '未命名规格',
url: url || null
};
}
四、完整SKU提取流程
javascript
async function extractAllSkuImages() {
// 1. 找到SKU容器
const container = findSkuContainer();
if (!container) {
console.log('未找到SKU容器');
return [];
}
// 2. 提取SKU项
const skuItems = extractSkuItems(container);
console.log(`发现 ${skuItems.length} 个SKU项`);
// 3. 过滤无效项(没有图片的项)
const validItems = skuItems.filter(item => item.url !== null);
// 4. 按名称去重
const uniqueMap = new Map();
for (const item of validItems) {
if (!uniqueMap.has(item.name)) {
uniqueMap.set(item.name, item);
}
}
return Array.from(uniqueMap.values());
}
五、主图与详情图的区分
SKU图是规格图,主图是轮播图,详情图是描述图。可以通过位置和尺寸区分:
javascript
function classifyImages(images) {
const result = {
main: [], // 主图
sku: [], // SKU图
detail: [] // 详情图
};
// 主图通常尺寸较大(>=400px)
// SKU图通常尺寸较小(<=150px)
// 详情图尺寸居中
for (const img of images) {
const width = img.width || 0;
if (width >= 400) {
result.main.push(img);
} else if (width <= 150) {
result.sku.push(img);
} else {
result.detail.push(img);
}
}
return result;
}
六、输出数据结构
javascript
// 提取结果示例
const skuImages = [
{ name: '红色', url: 'https://example.com/red.jpg' },
{ name: '蓝色', url: 'https://example.com/blue.jpg' },
{ name: '黑色', url: 'https://example.com/black.jpg' },
{ name: 'S码', url: 'https://example.com/s.jpg' },
{ name: 'M码', url: 'https://example.com/m.jpg' },
{ name: 'L码', url: 'https://example.com/l.jpg' }
];
七、文件归档方案
javascript
function organizeSkuImages(skuImages, outputDir, productTitle) {
const safeTitle = productTitle.replace(/[\\/*?:"<>|]/g, '_');
const basePath = `${outputDir}/${safeTitle}/SKU图`;
const results = [];
for (const sku of skuImages) {
const safeName = sku.name.replace(/[\\/*?:"<>|]/g, '_');
const filePath = `${basePath}/${safeName}.jpg`;
results.push({
name: sku.name,
url: sku.url,
path: filePath
});
}
return results;
}
八、完整采集流程示例
javascript
async function collectProductSkuImages() {
// 1. 等待页面加载
while (document.readyState !== 'complete') {
await sleep(200);
}
// 2. 等待SKU容器加载
let maxWait = 30;
while (maxWait-- > 0) {
if (findSkuContainer()) break;
await sleep(500);
}
// 3. 提取SKU图片
const skuImages = await extractAllSkuImages();
// 4. 获取商品标题
const title = document.title;
return {
title: title,
skuImages: skuImages,
count: skuImages.length
};
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
九、各平台差异对照表
| 平台 | SKU容器选择器 | SKU项选择器 | 名称提取位置 |
|---|---|---|---|
| 淘宝 | .tb-sku, .J_sku |
.sku-item |
.sku-name |
| 京东 | .sku-img-list |
.sku-img-item |
title属性 |
| 拼多多 | .sku-list |
.sku-item |
.sku-name |
| 1688 | .sku-list, .attribute-list |
.sku-item |
.sku-name |
十、总结
SKU图自动分类的核心技术点:
-
容器定位:使用多选择器策略兼容不同平台
-
属性提取:多级降级策略从不同位置提取规格名称
-
图片关联:将规格名称与对应图片URL绑定
-
智能归档:按规格名称自动分类命名
类似一键存图的工具已经将这些技术封装成成熟产品,用户无需编写代码,只需复制商品链接即可自动完成SKU图的分类归档,将原来5-10分钟的手工整理压缩到30秒。
免责声明:本文内容仅供技术交流和学习参考。电商平台的数据采集行为可能涉及平台服务条款、著作权法等法律问题。请确保遵守目标网站的《用户协议》和相关法律法规。因不当使用引发的法律风险由使用者自行承担。