京东商品参数对比工具

该脚本可用于对比不限数量的同类型商品(如:手机、笔记本)的详细参数

当前为 2024-02-08 提交的版本,查看 最新版本

// ==UserScript==
// @name         京东商品参数对比工具
// @namespace    http://tampermonkey.net/
// @version      2024-02-09
// @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 itemIDs = GM_getValue("jd-price-compare-item-ids", []);

    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() {
        return window.location.pathname.match(/(\d+)\.html/)[1];
    }

    function getPrice() {
        const itemID = getItemID();
        const targetSelector = `.price.J-p-${itemID}`;
        const targetNode = document.querySelector(targetSelector);
        return parseFloat(targetNode.innerText);
    }

    function getBasicInfo() {
        const basicInfoElement = document.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() {
        const mainInfoElements = document.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() {
        const packageListElement = document.querySelector('.package-list p');
        return packageListElement.textContent.trim();
    }

    function parseItem() {
        pollUntil(() => (!isNaN(getPrice())));
        let price = getPrice();
        let basicInfo = getBasicInfo();
        let mainInfo = getMainInfo();
        let packageList = getPackageList();
        let itemID = getItemID();

        let data = JSON.stringify({
            "商品编号": itemID,
            "基本信息": basicInfo,
            "主体信息": mainInfo,
            "包装信息": packageList,
            "价格": price,
        })
        return data;
    }

    function appendList(id) {
        let endpoint = "https://jd-compare.authu.online/api/v1/item";
        fetch(endpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(parseItem())
        })
            .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", []);
        console.log(itemIdList);
        let itemIdSet = new Set(itemIdList)
        itemIdSet.add(id);
        GM_setValue("jd-price-compare-item-ids", Array.from(itemIdSet.values()));
    }

    function createList() {
        let itemIdList = GM_getValue("jd-price-compare-item-ids", []);
        let endpoint = `https://jd-compare.authu.online/api/v1/list`;
        let listId = fetch(endpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(itemIdList)
        })
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }
            return response.text();
        })
        .then(data => {
            console.log("aaa"+data);
            return compareList(data);
        })
        .catch(error => {
            console.error('Error:', error);
        });
        return listId;
    }

    function compareList(listId) {
        let endpoint = `https://jd-compare.authu.online/api/v1/list/${listId}/compare`;
        console.log(endpoint);
        let resultUrl = fetch(endpoint)
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }
            return response.text();
        })
        .then(data => {
            window.open(data);
            GM_setValue("jd-price-compare-item-ids", []);
        })
        .catch(error => {
            console.error('Error:', error);
        });
        return resultUrl;
    }
    function addButton() {
        var compareButton = document.createElement('a');
        compareButton.href = '#';
        compareButton.id = 'jd-price-compare-add-button';
        compareButton.textContent = `加入对比清单 (${itemIDs.length})`;
        compareButton.className = 'btn-special1 btn-lg';
        compareButton.addEventListener("click", function () {
            appendList(getItemID());
            let itemIDs = GM_getValue("jd-price-compare-item-ids", []);
            compareButton.textContent = `加入对比清单 (${itemIDs.length})`;
        });
        var cartButtton = document.getElementById('InitCartUrl');
        cartButtton.parentNode.insertBefore(compareButton, cartButtton.nextSibling);
    }

    function compareButton() {
        var compareButton = document.createElement('a');
        compareButton.href = '#';
        compareButton.id = 'jd-price-compare-start-button';
        compareButton.textContent = '开始对比';
        compareButton.className = 'btn-special1 btn-lg';
        compareButton.addEventListener("click",function () {
            createList();
        });
        var cartButtton = document.getElementById('InitCartUrl');
        cartButtton.parentNode.insertBefore(compareButton, cartButtton.nextSibling);
    }

    function main() {
        compareButton();
        addButton();
    }

    window.addEventListener('load', main);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址