Greasy Fork is available in English.
京东(jd.com)商品列表页面的增强程序,增强了显示单价功能,帮助你在京东(jingdong)找到最便宜的商品
当前为
// ==UserScript==
// @name 京东单价助手
// @namespace http://greasyfork.org/
// @version 1.08
// @description 京东(jd.com)商品列表页面的增强程序,增强了显示单价功能,帮助你在京东(jingdong)找到最便宜的商品
// @author Yarmu
// @match *://search.jd.com/*
// @match *://list.jd.com/*
// @match *://item.jd.com/*
// @grant none
// @supportURL http://greasyfork.icu/zh-CN/scripts/30522-%E4%BA%AC%E4%B8%9C%E5%8D%95%E4%BB%B7%E5%8A%A9%E6%89%8B
// ==/UserScript==
(function() {
var host = window.location.host.toLowerCase();
if (host === 'list.jd.com' || host === 'search.jd.com') {
addPriceTipListener('.p-price', addListPriceTip, 1000);
} else if (host === 'item.jd.com') {
addPriceTipListener('.p-price', addItemPriceTip);
addPriceTipListener('.p-price-plus', addItemPriceTip);
}
})();
function addPriceTipListener(tag, func, time) {
var onModifiedFunc = function() {
$(this).unbind("DOMSubtreeModified");
func.call(this);
$(this).bind("DOMSubtreeModified", onModifiedFunc);
};
var eachCallFunc = function() {
$(tag).each(function() {
if (!$(this).attr('priceTip')) {
$(this).attr('priceTip', '1');
onModifiedFunc.call(this);
}
});
};
eachCallFunc();
if (time) {
setInterval(eachCallFunc, time);
}
}
function addListPriceTip() {
var priceItem = $(this).find('strong i');
var price = getFloat(priceItem.text());
if (isNaN(price)) {
priceItem = $(this).find('strong span');
price = getFloat(priceItem.text());
if (isNaN(price)) {
priceItem = $(this).find('strong');
price = getFloat(priceItem.text());
if (isNaN(price)) {
priceItem = $(this);
price = getFloat(priceItem.text());
}
}
}
if (isNaN(price)) return;
var title = null;
var index = 0;
$(this).parent().find('.p-scroll .ps-wrap .ps-main .ps-item a').each(function(idx) {
if ($(this).attr('class') === 'curr' && $(this).attr('title')) {
title = $(this).attr('title').trim();
index = idx;
return false;
}
});
var unit = getUnit(title, price);
if (unit === null && index === 0) {
title = $(this).parent().find('.p-name a em').text().trim();
if (!title) {
title = $(this).parent().find('.p-name a').text().trim();
}
unit = getUnit(title, price);
}
if (unit === null) return;
var htm = ' (' + unit.price + '/' + unit.unit + ')';
title = '(助手估重: ' + unit.capacity + unit.unit + ' = "' + unit.tip + '")\n' + title;
priceItem.append(htm);
var tipItem = $(this).parent().find('.p-name a');
setTimeout(function() {
tipItem.attr('title', title);
}, 1000);
}
function addItemPriceTip() {
var priceItem = $(this).find('.price');
var price = getFloat(priceItem.text());
if (isNaN(price)) return;
var title = $('.sku-name').text().trim();
var unit = getUnit(title, price);
if (unit === null) return;
var htm = ' (' + unit.price + '/' + unit.unit + ')';
title = ' (助手估重: ' + unit.capacity + unit.unit + ' = "' + unit.tip + '")';
priceItem.append(htm);
if (!window.hasAddItemPriceTip) {
window.hasAddItemPriceTip = true;
setTimeout(function() {
$('#summary-weight .dd').append(title);
}, 1000);
}
}
function getUnit(title, price) {
if (!title) return null;
if (price <= 0) return null;
//处理包含:的情况
if (title.indexOf(':') != -1){
var titles = title.split(':');
for (var t=0; t<titles.length; ++t) {
var res = getUnit(titles[t], price);
if (res) return res;
}
}
var regQuant = "个只瓶罐听桶条提卷包袋件盒箱组串册副份双对块本束杯枚枝根片盆盘碗粒颗管";
var regWeigh = "g|kg|ml|l|千克|克|斤|公斤|毫升|升";
var regFloat = "\\d+\\.?\\d*?(?:\\s*-\\s*\\d+\\.?\\d*?)?";
//处理有总重量的情况
var reg0 = new RegExp('[总净]重量?约?\\s*('+regFloat+')\\s*('+regWeigh+')');
var pos0 = {i: 0, pCap: 1, pUnit: 2, pCount: 3};
//处理数量前置的情况
var reg1 = new RegExp('\\b(\\d+)\\s*['+regQuant+']?\\s*[*x×'+regQuant+']\\s*('+regFloat+')\\s*('+regWeigh+')', 'ig');
var pos1 = {i: 1, pCap: 2, pUnit: 3, pCount: 1};
//处理数量后置的情况
var reg2 = new RegExp('\\b('+regFloat+')\\s*('+regWeigh+')(?:\\s*\\/?[\\u4e00-\\u9fa5]*)((?:\\s*[*x×'+regQuant+']\\s*\\d+[\\u4e00-\\u9fa5]?)*)', 'ig');
var pos2 = {i: 2, pCap: 1, pUnit: 2, pCount: 3};
var reg, pos;
//处理有括号的情况
var name = title.replace(/[((][^))]+(\)|)|$)/g, '');
if (reg0.test(title)) {
name = title; reg = reg0; pos = pos0;
} else if (reg1.test(name)) {
reg = reg1; pos = pos1;
} else if (reg2.test(name)) {
reg = reg2; pos = pos2;
} else if (reg1.test(title)) {
name = title; reg = reg1; pos = pos1;
} else {
name = title; reg = reg2; pos = pos2;
}
//处理有赠送的情况
var isOnlyOne = !/[++送和]/i.test(name);
var match = null;
var cap = 0, count = 0, lastMul = 0;
var un = '', tip = '';
reg.lastIndex = 0;
while ((match = reg.exec(name))) {
var capacity;
var caps = match[pos.pCap].split('-');
if (caps.length == 2) {
capacity = (parseFloat(caps[0].trim()) + parseFloat(caps[1].trim()))/2;
} else {
capacity = parseFloat(match[pos.pCap].trim());
}
if (match.length > 3 && match[pos.pCount]) {
var multiple = match[pos.pCount].match(/\d+/g);
if (multiple) for (var i=0; i<multiple.length; ++i) {
lastMul = parseInt(multiple[i]);
capacity *= lastMul;
}
}
if (capacity <= 0) {
continue;
}
var unit = match[pos.pUnit].toLowerCase();
if (unit === 'g' || unit === '克') {
capacity /= 1000;
unit = 'kg';
} else if (unit === '千克' || unit === '公斤') {
unit = 'kg';
} else if (unit === '斤') {
capacity /= 2;
unit = 'kg';
} else if (unit === 'ml' || unit === '毫升') {
capacity /= 1000;
unit = 'L';
} else if (unit === 'l' || unit === '升') {
unit = 'L';
}
if (un === '' || un === unit) {
un = unit;
tip += match[0] + ' ';
cap += capacity;
++count;
}
if (isOnlyOne) {
break;
}
}
//处理数量在其他位置的情况
if (count == 1 && pos.i !== 0) {
var regMul = '\\b(\\d+)['+regQuant+']';//(?:礼盒)?装
reg = new RegExp(regMul, 'i');
match = reg.exec(title);
if (match && lastMul != parseInt(match[1])) {
cap *= parseInt(match[1]);
tip += match[0];
}
}
if (cap > 0) return {
capacity: Math.round(cap * 10000) / 10000,
unit: un,
price: Math.round(parseFloat(price) / cap * 100) / 100,
tip: tip.trim()
};
else return null;
}
function getFloat(str) {
str = str.replace('¥','').trim();
if (!/^\d+\.?\d*$/.test(str)) return NaN;
return parseFloat(str);
}