您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
该脚本可用于对比不限数量的同类型商品(如:手机、笔记本)的详细参数
当前为
// ==UserScript== // @name 京东商品参数对比工具 // @namespace http://tampermonkey.net/ // @version 4.0.0 // @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.authu.online"; var version = '4.0.0'; 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 => { console.log('Response:', data); }) .catch(error => { console.error('Error:', error); }); 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())); } function createList() { let itemIdList = GM_getValue("jd-price-compare-item-ids", []); 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 => { return compareList(data._id); }) .catch(error => { console.error('Error:', error); }); return listId; } function compareList(listId) { 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 => { GM_setValue("jd-price-compare-item-ids", []); window.open(`${apiServer}/${data}`); }) .catch(error => { console.error('Error:', error); }); return resultUrl; } function addSingleButton() { let compareButton = document.createElement('a'); 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(); appendList(getItemID(document)); updateCompareButton(); }); let cartButtton = document.querySelector('#preview > div.preview-info > div.left-btns.shieldShopInfo'); cartButtton.appendChild(compareButton); } function addAllButton() { let compareButton = document.createElement('a'); 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) { 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 compareButton() { 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 main() { addSingleButton(); if (relatedItemIDs.length > 1) { addAllButton(); } compareButton(); setInterval(updateCompareButton, 512); } window.addEventListener('load', main); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址