引言
很多开发者在问:"电商图片下载工具是怎么区分主图和颜色图的?""自动分类的技术原理是什么?"
电商图片下载工具的核心能力之一,是将提取的图片智能分类为主图、属性图(SKU图)、详情图。本文从技术角度深入解析分类算法的实现原理。
一、分类任务的难点
电商页面的图片数量多、类型杂,分类面临以下挑战:
| 挑战 | 说明 |
|---|---|
| 结构差异 | 不同平台的DOM结构完全不同 |
| 动态加载 | 属性图可能通过JS动态切换 |
| 特征模糊 | 某些图片既像主图又像属性图 |
| 数量不定 | 每种类型的图片数量不固定 |
二、分类特征体系
2.1 多维特征识别
| 图片类型 | 位置特征 | 尺寸特征 | 数量特征 | 关联特征 |
|---|---|---|---|---|
| 主图 | 轮播图容器内 | 较大(800x800+) | 3-8张 | 无 |
| 属性图 | SKU容器内 | 较小(100x100-200x200) | 不定 | 与规格关联 |
| 详情图 | 描述容器内 | 长图(宽800+,高不定) | 不定 | 无 |
三、分类算法实现
3.1 容器定位策略
javascript
class ImageClassifier {
constructor() {
this.result = {
main: [], // 主图
sku: [], // 属性图
detail: [] // 详情图
};
// 主图容器选择器(按优先级)
this.mainSelectors = [
'.J_UlThumb', '.tb-thumb', '.tb-main-pic',
'.carousel', '.swiper', '.product-images',
'[class*="main-image"]', '[class*="thumbnail"]'
];
// 属性图容器选择器
this.skuSelectors = [
'.tb-sku', '.J_sku', '.sku', '.attribute',
'[class*="sku"]', '[class*="spec"]', '[class*="attribute"]'
];
// 详情图容器选择器
this.detailSelectors = [
'#description', '.desc', '.detail',
'[class*="description"]', '[class*="detail"]'
];
}
classify(dom) {
this.findMainImages(dom);
this.findSkuImages(dom);
this.findDetailImages(dom);
return this.result;
}
findMainImages(dom) {
for (const selector of this.mainSelectors) {
const container = dom.querySelector(selector);
if (container) {
this.extractFromContainer(container, 'main');
break; // 找到第一个有效容器即停止
}
}
}
findSkuImages(dom) {
for (const selector of this.skuSelectors) {
const container = dom.querySelector(selector);
if (container) {
this.extractFromContainer(container, 'sku');
break;
}
}
}
extractFromContainer(container, type) {
const images = container.querySelectorAll('img');
images.forEach(img => {
const url = this.getHighQualityUrl(img);
if (url && !this.isDuplicate(url, type)) {
this.result[type].push({
url: url,
type: type,
name: this.getImageName(img, type)
});
}
});
}
}
3.2 原图URL转换
javascript
getHighQualityUrl(img) {
let url = img.src ||
img.getAttribute('data-src') ||
img.getAttribute('data-original');
if (!url || !url.startsWith('http')) return null;
if (url.includes('1x1') || url.includes('blank.gif')) return null;
if (url.startsWith('data:image')) return null;
// 淘宝/天猫:去除尺寸后缀
url = url.replace(/_\d+x\d+\./g, '.');
url = url.replace(/\.sum\./g, '.');
// 京东:去除缩略图参数
url = url.replace(/!q\d+$/, '');
url = url.replace(/\.n\.jpg/, '.jpg');
// 拼多多:去除参数
url = url.split('?')[0];
return url;
}
3.3 属性名称提取
javascript
getImageName(img, type) {
if (type === 'sku') {
// 尝试从alt属性获取
if (img.alt && !img.alt.includes('http')) {
return this.sanitizeName(img.alt);
}
// 尝试从父级元素获取属性名称
const parent = img.parentElement;
if (parent) {
const text = parent.textContent || parent.getAttribute('title');
if (text && text.length < 20) {
return this.sanitizeName(text);
}
}
// 尝试从相邻元素获取
const sibling = img.nextElementSibling || img.previousElementSibling;
if (sibling && sibling.textContent) {
return this.sanitizeName(sibling.textContent);
}
}
return `${type}_${Date.now()}`;
}
sanitizeName(name) {
// 清理非法字符
return name.trim().replace(/[\\/*?:"<>|]/g, '_').substring(0, 50);
}
四、去重与过滤
javascript
isDuplicate(url, type) {
// 检查是否已在同类中
const exists = this.result[type].some(item => item.url === url);
if (exists) return true;
// 跨类型去重(主图和属性图不应重复)
for (const t of ['main', 'sku']) {
if (t !== type && this.result[t].some(item => item.url === url)) {
return true;
}
}
return false;
}
filterInvalidImages(images) {
return images.filter(img => {
// 过滤无效图片
if (!img.url) return false;
if (img.url.includes('icon') && img.url.includes('20x20')) return false;
if (img.url.includes('loading') || img.url.includes('placeholder')) return false;
return true;
});
}
五、兜底策略
当无法通过容器定位时,采用特征匹配兜底:
javascript
fallbackClassify(images) {
const result = { main: [], sku: [], detail: [] };
images.forEach(img => {
// 基于尺寸判断
if (img.width >= 400 && img.height >= 400) {
// 大图倾向主图
if (result.main.length < 8) {
result.main.push(img);
} else {
result.detail.push(img);
}
}
else if (img.width <= 200 && img.height <= 200) {
// 小图倾向属性图
result.sku.push(img);
}
else {
result.detail.push(img);
}
});
return result;
}
六、性能优化
javascript
// 批量处理优化
class BatchClassifier {
constructor(batchSize = 50) {
this.batchSize = batchSize;
}
async classifyLargePage(dom) {
const allImages = dom.querySelectorAll('img');
const batches = [];
// 分批处理,避免阻塞
for (let i = 0; i < allImages.length; i += this.batchSize) {
batches.push(Array.from(allImages).slice(i, i + this.batchSize));
}
const results = [];
for (const batch of batches) {
results.push(await this.processBatch(batch));
// 让出主线程
await new Promise(resolve => setTimeout(resolve, 0));
}
return this.mergeResults(results);
}
}
七、代表产品实测
以一键存图为例,分类算法实测数据:
| 指标 | 数据 |
|---|---|
| 主图识别准确率 | 99%+ |
| 属性图识别准确率 | 95%+ |
| 详情图识别准确率 | 98%+ |
| 平均处理时间 | <100ms |
八、总结
电商图片智能分类的核心技术:
| 环节 | 关键技术 |
|---|---|
| 容器定位 | 多级选择器匹配 |
| 特征提取 | 尺寸、位置、关联元素 |
| 去重过滤 | URL去重、跨类型去重 |
| 兜底策略 | 基于尺寸特征的分类 |
百度搜索"一键存图"可查看完整的分类算法实现效果。