// ==UserScript==
// @name JD接口抓取SKU商品名图片-内容数分组版
// @namespace jd-api-sku-img-content-group
// @version 3.0
// @match *://*.jd.com/*
// @match *://*.m.jd.com/*
// @grant GM_download
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
const downloaded = new Set();
function safeName(str) {
return String(str || "")
.replace(/[\\/:*?"<>|]/g, "_")
.replace(/\s+/g, " ")
.trim()
.slice(0, 120);
}
function cleanImg(url) {
if (!url) return "";
url = String(url).trim();
if (url.startsWith("//")) {
url = "https:" + url;
}
// 重点修复:
// https://m.360buyimg.com/ceco/s500x0_jfs/...
// 变成:
// https://m.360buyimg.com/ceco/jfs/...
url = url.replace(/\/s\d+x\d+_jfs\//g, "/jfs/");
// 兜底去掉 s500x0_、s250x250_、s800x800_ 等
url = url.replace(/s\d+x\d+_/g, "");
return url;
}
function getContentNum(value) {
if (value === undefined || value === null) return 0;
let str = String(value).trim();
// 例如:30+、5+、内容数3
let match = str.match(/\d+/);
if (!match) return 0;
return parseInt(match[0], 10) || 0;
}
function getContentGroup(value) {
const num = getContentNum(value);
if (num <= 5) {
return "01_内容数0-5";
}
if (num <= 10) {
return "02_内容数5-10";
}
if (num <= 20) {
return "03_内容数10-20";
}
if (num <= 50) {
return "04_内容数21-50";
}
return "05_内容数50以上";
}
function downloadSku(item) {
if (!item || !item.skuBasic) return;
const sku = item.skuBasic.sku || "";
const title = item.skuBasic.skuName || "";
const img = cleanImg(item.skuBasic.img || "");
const contentCount =
item.skuStatistics?.contentCount
|| item.skuStatistics?.contentCountBlur
|| "0";
if (!sku || !title || !img) return;
const key = sku + "_" + img;
if (downloaded.has(key)) return;
downloaded.add(key);
const groupName = getContentGroup(contentCount);
const folderName = safeName(sku) + "----" + safeName(title);
const savePath = groupName + "/" + folderName + "/0.jpg";
console.log("准备下载:", {
sku: sku,
title: title,
contentCount: contentCount,
group: groupName,
img: img,
savePath: savePath
});
GM_download({
url: img,
name: savePath,
saveAs: false,
onload: function () {
console.log("下载成功:", savePath);
},
onerror: function (e) {
console.log("下载失败:", savePath, img, e);
}
});
}
function handleJson(json) {
try {
if (!json || json.code !== 0) return;
const skus = json?.data?.skus;
if (!Array.isArray(skus) || skus.length === 0) return;
console.log("接口检测到SKU数量:", skus.length);
skus.forEach(downloadSku);
} catch (e) {
console.log("解析SKU失败:", e);
}
}
// 拦截 fetch
const originalFetch = window.fetch;
window.fetch = function () {
return originalFetch.apply(this, arguments).then(function (response) {
try {
const url = response.url || "";
if (url.includes("api.m.jd.com")) {
response.clone().json().then(function (json) {
handleJson(json);
}).catch(function () {});
}
} catch (e) {}
return response;
});
};
// 拦截 XMLHttpRequest
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function (method, url) {
this._jd_url = url;
return originalOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function () {
this.addEventListener("load", function () {
try {
const url = this._jd_url || "";
if (!url.includes("api.m.jd.com")) return;
const json = JSON.parse(this.responseText);
handleJson(json);
} catch (e) {}
});
return originalSend.apply(this, arguments);
};
function addButton() {
if (document.getElementById("jdSkuContentGroupBtn")) return;
const btn = document.createElement("button");
btn.id = "jdSkuContentGroupBtn";
btn.innerText = "监听SKU图片";
btn.style.cssText = `
position: fixed;
right: 20px;
top: 120px;
z-index: 999999;
padding: 10px 16px;
background: #e1251b;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
box-shadow: 0 4px 12px rgba(0,0,0,.2);
`;
btn.onclick = function () {
alert("脚本正在监听 api.m.jd.com 接口,请刷新页面、翻页或滚动加载商品。");
};
document.body.appendChild(btn);
}
window.addEventListener("DOMContentLoaded", addButton);
})();
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。