您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
该脚本可用于对比不限数量的同类型商品(如:手机、笔记本)的详细参数
当前为
// ==UserScript== // @name 京东商品参数对比工具 // @namespace http://tampermonkey.net/ // @version 2077.0.4 // @description 该脚本可用于对比不限数量的同类型商品(如:手机、笔记本)的详细参数 // @author Yihang Wang <[email protected]> // @match https://item.jd.com/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function () { 'use strict'; var apiServer = "https://jd-compare.overflow.host"; var version = '2077.0.4'; var itemIDs = GM_getValue("jd-price-compare-item-ids", []); var relatedItemIDs = getRelatedItemIDs(document); var userID = getUserID(); function pollUntil(conditionFn, interval = 1000, maxAttempts = 10) { return new Promise((resolve, reject) => { let attempts = 0; function checkCondition() { if (conditionFn()) { resolve(); } else if (attempts < maxAttempts) { attempts++; setTimeout(checkCondition, interval); } else { reject(new Error('Polling timed out')); } } checkCondition(); }); } function getItemID(doc) { let a = doc.querySelector('a.follow.J-follow[data-id]'); return a ? a.getAttribute('data-id') : "unknown"; } function getRelatedItemIDs(doc) { var dataSkuValues = [getItemID(doc)]; if (Object.keys(pageConfig.product.colorSize).length > 0) { pageConfig.product.colorSize.forEach(function (item) { dataSkuValues.push(item.skuId.toString()); }); } let itemIdSet = new Set(dataSkuValues); return Array.from(itemIdSet.values()); } function getPrice(doc) { const itemID = getItemID(doc); const targetSelector = `.price.J-p-${itemID}`; const targetNode = doc.querySelector(targetSelector); return parseFloat(targetNode.innerText); } function getBasicInfo(doc) { const basicInfoElement = doc.querySelector('#detail > div.tab-con > div:nth-child(1) > div.p-parameter'); const basicInfo = {}; basicInfoElement.querySelectorAll('li').forEach(dl => { let text = dl.textContent.trim(); console.log(text); if (text.indexOf(":") < 0) { console.error(`invalid basic info: ${text}, colon is not present`); return; } let items = text.split(":"); if (items.length != 2) { console.error(`invalid basic info: ${text}, incorrect number of items`); return; } const key = items[0] const value = items[1] basicInfo[key] = value; }); return basicInfo; } function getMainInfo(doc) { const mainInfoElements = doc.querySelectorAll('.Ptable-item'); const mainInfo = {}; mainInfoElements.forEach(item => { const key = item.querySelector('h3').textContent.trim(); const values = {}; item.querySelectorAll('dl').forEach(dl => { const detailKey = dl.querySelector('dt').textContent.trim(); const detailValue = dl.querySelector('dd').textContent.trim(); values[detailKey] = detailValue; }); mainInfo[key] = values; }); return mainInfo; } function getPackageList(doc) { const packageListElement = doc.querySelector('.package-list p'); return packageListElement.textContent.trim(); } function getImageUrl(doc) { const imageElement = doc.querySelector("#spec-list > ul > li:nth-child(1) > img"); // https://img13.360buyimg.com/ n5/s54x54_jfs/t1/ 216364/18/36214/152585/65ade2ffFfabd3665/a7fe2701bfcd0c0a.jpg.avif // https://img10.360buyimg.com/ n0/jfs/t1/ 235161/18/13361/139190/65bef13aF2b8cfc2f/d4f68e1e90bd1677.jpg.avif let items = imageElement.src.split("/"); items[3] = 'n0' items[4] = 'jfs' items[5] = 't1' return items.join("/"); } function parseItemWithDocument(doc) { let basicInfo = getBasicInfo(doc); let mainInfo = getMainInfo(doc); let packageList = getPackageList(doc); let imageUrl = getImageUrl(doc); let itemID = getItemID(doc); let data = { "商品编号": itemID, "基本信息": basicInfo, "主体信息": mainInfo, "包装信息": packageList, "价格": 'N/A', "图片": imageUrl, }; return data; } function parseItemByID(itemID) { return new Promise(function (resolve, reject) { let endpoint = `https://item.jd.com/${itemID}.html`; fetch(endpoint) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } resolve(response.text()); }) .catch(error => { console.error('Error:', error); }); }); } async function parseItem(itemID) { if (itemID == getItemID(document)) { pollUntil(() => (!isNaN(getPrice(document)))); let price = getPrice(document); let data = parseItemWithDocument(document); data["价格"] = price; return data; } else { let html = await parseItemByID(itemID); let parser = new DOMParser(); let doc = parser.parseFromString(html, 'text/html'); let item = parseItemWithDocument(doc); return item; } } async function appendList(itemID) { let endpoint = `${apiServer}/api/v1/item`; let item = await parseItem(itemID); let body = JSON.stringify(item); fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Jd-Compare-Version': version, 'Jd-Compare-User-Id': userID, }, body: body, }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } console.log(response); return response.json(); }) .then(data => { let itemIdList = GM_getValue("jd-price-compare-item-ids", []); let itemIdSet = new Set(itemIdList) itemIdSet.add(itemID); GM_setValue("jd-price-compare-item-ids", Array.from(itemIdSet.values())); let statusLine = document.getElementById('jd-price-compare-status-line'); statusLine.textContent = `已成功添加 ${itemIdSet.size} 个待对比商品`; }) .catch(error => { console.error('Error:', error); }); } function createList() { let itemIdList = GM_getValue("jd-price-compare-item-ids", []); let statusLine = document.getElementById('jd-price-compare-status-line'); if (itemIdList.length == 0) { statusLine.textContent = `当前待对比商品列表为空,请先点击添加商品按钮。`; return } statusLine.textContent = `正在创建 ${itemIdList.length} 个商品的对比列表...`; let endpoint = `${apiServer}/api/v1/list`; let listId = fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Jd-Compare-Version': version, 'Jd-Compare-User-Id': userID, }, body: JSON.stringify(itemIdList) }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json(); }) .then(data => { statusLine.textContent = `对比成功,正在自动打开结果页面...`; return compareList(data._id); }) .catch(error => { console.error('Error:', error); }); return listId; } function compareList(listId) { let statusLine = document.getElementById('jd-price-compare-status-line'); let endpoint = `${apiServer}/api/v1/list/${listId}/compare`; let resultUrl = fetch(endpoint, { method: 'GET', headers: { 'Jd-Compare-Version': version, 'Jd-Compare-User-Id': userID, }, }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.text(); }) .then(data => { let link = document.createElement('a'); let url = `${apiServer}/${data}`; link.href = url; link.textContent = `列表 ID: ${listId} `; // 修正属性名,应该是textContent statusLine.textContent = `对比完成,正在打开商品对比结果页面。`; statusLine.appendChild(document.createElement("br")); // 创建并添加<p>元素 let p = document.createElement("p"); p.textContent = `如未打开,也可以直接点击下方链接`; statusLine.appendChild(p); statusLine.appendChild(link); statusLine.appendChild(document.createElement("br")); // 创建并添加文本节点 let textNode = document.createTextNode(`您可以继续添加其他待对比商品。`); statusLine.appendChild(textNode); GM_setValue("jd-price-compare-item-ids", []); window.open(url); }) .catch(error => { console.error('Error:', error); }); return resultUrl; } function addSingleButton() { let compareButton = document.createElement('a'); let statusLine = document.getElementById('jd-price-compare-status-line'); compareButton.href = '#'; compareButton.id = 'jd-price-compare-add-single-button'; compareButton.textContent = `添加本商品`; compareButton.style.backgroundColor = '#3498db'; compareButton.style.color = '#ffffff'; compareButton.style.padding = '3px'; compareButton.addEventListener("click", function (event) { event.preventDefault(); let itemID = getItemID(document); statusLine.textContent = `正在获取商品(ID:${itemID})详信息...`; appendList(itemID); updateCompareButton(); }); let cartButtton = document.querySelector('#preview > div.preview-info > div.left-btns.shieldShopInfo'); cartButtton.appendChild(compareButton); } function addAllButton() { let compareButton = document.createElement('a'); let statusLine = document.getElementById('jd-price-compare-status-line'); compareButton.href = '#'; compareButton.id = 'jd-price-compare-add-all-button'; compareButton.textContent = `添加所有 ${relatedItemIDs.length} 个型号`; compareButton.style.backgroundColor = '#3498db'; compareButton.style.color = '#ffffff'; compareButton.style.padding = '3px'; compareButton.addEventListener("click", function (event) { event.preventDefault(); relatedItemIDs.forEach(function (itemID) { statusLine.textContent = `正在获取商品(ID:${itemID})详信息...`; appendList(itemID); }); }); let cartButtton = document.querySelector('#preview > div.preview-info > div.left-btns.shieldShopInfo'); cartButtton.appendChild(compareButton); } function updateCompareButton() { let element = document.getElementById('jd-price-compare-start-button'); let itemIdList = GM_getValue("jd-price-compare-item-ids", []); element.textContent = `开始对比 (${itemIdList.length})`; } function addCompareButton() { let compareButton = document.createElement('a'); compareButton.href = '#'; compareButton.id = 'jd-price-compare-start-button'; compareButton.style.backgroundColor = '#3498db'; compareButton.style.color = '#ffffff'; compareButton.style.padding = '3px'; compareButton.textContent = `开始对比 (${itemIDs.length})`; compareButton.addEventListener("click", function (event) { event.preventDefault(); createList(); }); let cartButtton = document.querySelector('#preview > div.preview-info > div.left-btns.shieldShopInfo'); cartButtton.appendChild(compareButton); } function getUserID() { let userID = GM_getValue("jd-price-compare-user-id", ""); if (userID == "") { userID = Math.random().toString(36).substring(2); GM_setValue("jd-price-compare-user-id", userID); } return userID; } function addStatusLine() { let statusLine = document.createElement('p'); statusLine.id = 'jd-price-compare-status-line'; statusLine.style.color = '#000000'; statusLine.style.padding = '3px'; statusLine.textContent = `京东商品参数对比工具 v${version}`; let statusLineDiv = document.createElement('div'); statusLineDiv.id = 'jd-price-compare-status-line-div'; statusLineDiv.style.textAlign = 'center'; statusLineDiv.appendChild(statusLine); let targetElement = document.querySelector('#preview > div.preview-info'); targetElement.parentNode.insertBefore(statusLineDiv, targetElement.nextSibling); } function main() { addStatusLine(); addSingleButton(); if (relatedItemIDs.length > 1) { addAllButton(); } addCompareButton(); setInterval(updateCompareButton, 512); } window.addEventListener('load', main); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址