一号店单价助手

一号店(yhd.com)单价助手,补全了商品列表中有些商品没标单价的信息,帮助你在1号店(yihaodian)找到最划算的商品

  1. // ==UserScript==
  2. // @name 一号店单价助手
  3. // @namespace http://gf.qytechs.cn/
  4. // @version 1.01
  5. // @description 一号店(yhd.com)单价助手,补全了商品列表中有些商品没标单价的信息,帮助你在1号店(yihaodian)找到最划算的商品
  6. // @author Yarmu
  7. // @match *://list.yhd.com/*
  8. // @match *://search.yhd.com/*
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @supportURL http://gf.qytechs.cn/zh-CN/users/41708-yarmu
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. var enabled = GM_getValue('yhd_price_tip_enabled', true);
  16. addListPriceButton(enabled);
  17. if (enabled) {
  18. addPriceTipListener('.proPrice', addListPriceTip, 1000);
  19. }
  20. })();
  21.  
  22. function addPriceTipListener(tag, func, time) {
  23. var eachCallFunc = function() {
  24. $(tag).each(function() {
  25. if (!$(this).attr('priceTip')) {
  26. $(this).attr('priceTip', '1');
  27. func.call(this);
  28. }
  29. });
  30. };
  31. eachCallFunc();
  32. if (time) {
  33. setInterval(eachCallFunc, time);
  34. }
  35. }
  36.  
  37. function addListPriceTip() {
  38. var infoItem = $(this).find('.num');
  39. if (infoItem.length === 0) infoItem = $(this).find('.price');
  40. var price = infoItem.attr('yhdprice');
  41. console.log(price);
  42. if (!price) return;
  43.  
  44. var capacity = infoItem.attr('diapernum');
  45. var unitType = infoItem.attr('productunit');
  46. var unitItem = $(this).find('.unit_price');
  47. console.log([price, capacity, unitType, unitItem.length]);
  48. if (capacity && unitType && unitItem.length) return;
  49.  
  50. var titleItem = $(this).parent().find('.proName a');
  51. if(titleItem.length === 0) titleItem = $(this).parent().find('.title a');
  52. var title = titleItem.text().trim();
  53. price = parseFloat(price);
  54. capacity = parseFloat(capacity);
  55.  
  56. var unit;
  57. if (!isNaN(capacity) && capacity > 0 && unitType && unitItem.length === 0) {
  58. if (unitType == '4') {
  59. unitType = 'L';
  60. capacity /= 1000;
  61. price /= capacity;
  62. } else {
  63. unitType = '500g';
  64. capacity /= 500;
  65. price /= capacity;
  66. }
  67. unit = {
  68. price: Math.round(price * 100) / 100,
  69. capacity: Math.round(capacity * 10000) / 10000,
  70. unit: unitType
  71. };
  72. } else {
  73. unit = getUnit(title, price);
  74. if (unit === null) return;
  75. }
  76.  
  77. var htm = '(¥' + unit.price + '/' + unit.unit + ')';
  78. if (unit.tip) {
  79. title = '( 助手估重: ' + unit.capacity + unit.unit + ' = ' + unit.tip + ' )\n' + title;
  80. titleItem.attr('title', title);
  81. }
  82. if (!unitItem.length) {
  83. unitItem = $('<span class="unit_price"></span>');
  84. $(this).append(unitItem);
  85. }
  86. unitItem.html(htm);
  87. }
  88.  
  89. function addListPriceButton(isEnabled) {
  90. var button = $('#priceTipButton');
  91. if (button.length > 0) return;
  92. button = $('<a' + (isEnabled? ' class="cur"': '') + ' href="javascript:void(0);">单价助手</a>');
  93. $('.sort_b').append(button);
  94. button.click(function() {
  95. GM_setValue('yhd_price_tip_enabled', !isEnabled);
  96. $(this).attr('class', (!isEnabled? 'cur': ''));
  97. location.reload();
  98. });
  99. }
  100.  
  101. function getUnit(title, price) {
  102. if (!title) return null;
  103. if (price <= 0) return null;
  104.  
  105. //处理包含:和送的情况
  106. if (title.match(/:|[))】]送/)){
  107. var titles = title.split(/:|[))】]送/);
  108. for (var t=0; t<titles.length; ++t) {
  109. var res = getUnit(titles[t], price);
  110. if (res) return res;
  111. }
  112. }
  113.  
  114. var regQuant = "个只瓶罐听桶提卷包袋件盒箱组副份盆盘碗支";
  115. var regWeigh = "g|kg|ml|l|千克|克|斤|公斤|毫升|升";
  116. var regFloat = "\\d+\\.?\\d*?(?:\\s*-\\s*\\d+\\.?\\d*?)?";
  117. //处理有总重量的情况
  118. var reg0 = new RegExp('(?:[总净]重量?约?|\\s约)\\s*('+regFloat+')\\s*('+regWeigh+')', 'g');
  119. var pos0 = {i: 0, pCap: 1, pUnit: 2, pCount: 3};
  120. //处理数量前置的情况
  121. var reg1 = new RegExp('(\\d+)\\s*['+regQuant+']?\\s*[*x×'+regQuant+']\\s*('+regFloat+')\\s*('+regWeigh+')', 'ig');
  122. var pos1 = {i: 1, pCap: 2, pUnit: 3, pCount: 1};
  123. //处理数量后置的情况
  124. var reg2 = new RegExp('('+regFloat+')\\s*('+regWeigh+')(?:\\s*\\/?[\\u4e00-\\u9fa5]*)((?:\\s*[*x×'+regQuant+']\\s*\\d+[\\u4e00-\\u9fa5]?)*)', 'ig');
  125. var pos2 = {i: 2, pCap: 1, pUnit: 2, pCount: 3};
  126.  
  127. var reg, pos;
  128. //处理有括号的情况
  129. var name = title.replace(/[((【][^))】]+?(\)|)|】|$)/g, '');
  130. if (reg0.test(title)) {
  131. name = title; reg = reg0; pos = pos0;
  132. } else if (reg1.test(name)) {
  133. reg = reg1; pos = pos1;
  134. } else if (reg2.test(name)) {
  135. reg = reg2; pos = pos2;
  136. } else if (reg1.test(title)) {
  137. name = title; reg = reg1; pos = pos1;
  138. } else {
  139. name = title; reg = reg2; pos = pos2;
  140. }
  141. //处理套装的情况
  142. var isOnlyOne = !/[++送和]/i.test(name);
  143.  
  144. var match = null;
  145. var cap = 0, count = 0, lastMul = 1;
  146. var un = '', tip = '';
  147. reg.lastIndex = 0;
  148. while ((match = reg.exec(name))) {
  149. var capacity;
  150. var caps = match[pos.pCap].split('-');
  151. if (caps.length == 2) {
  152. capacity = (parseFloat(caps[0].trim()) + parseFloat(caps[1].trim()))/2;
  153. } else {
  154. capacity = parseFloat(match[pos.pCap].trim());
  155. }
  156. if (match.length > 3 && match[pos.pCount]) {
  157. var multiple = match[pos.pCount].match(/\d+/g);
  158. if (multiple) for (var i=0; i<multiple.length; ++i) {
  159. lastMul = parseInt(multiple[i]);
  160. capacity *= lastMul;
  161. }
  162. }
  163. if (capacity <= 0) {
  164. continue;
  165. }
  166. var unit = match[pos.pUnit].toLowerCase();
  167.  
  168. if (unit === 'g' || unit === '克') {
  169. capacity /= 500;
  170. unit = '500g';
  171. } else if (unit === 'kg' || unit === '千克' || unit === '公斤') {
  172. capacity *= 2;
  173. unit = '500g';
  174. } else if (unit === '斤') {
  175. //capacity /= 2;
  176. unit = '500g';
  177. } else if (unit === 'ml' || unit === '毫升') {
  178. capacity /= 1000;
  179. unit = 'L';
  180. } else if (unit === 'l' || unit === '升') {
  181. unit = 'L';
  182. }
  183. if (un === '' || un === unit) {
  184. //处理重复出现的情况
  185. if (isOnlyOne) {
  186. if (capacity > cap) {
  187. tip = ''; cap = 0; count = 0;
  188. } else {
  189. continue;
  190. }
  191. }
  192. un = unit;
  193. tip += match[0] + ' ';
  194. cap += capacity;
  195. ++count;
  196. }
  197. }
  198.  
  199. //处理数量在其他位置的情况
  200. if (count == 1 && pos.i !== 0) {
  201. var regZhn = '两一二三四五六七八九十';
  202. var regMul = '(?:[^*x×满\\d])\\s*(\\d+|['+regZhn+'])['+regQuant+'](?!\\d+折|松)';
  203. reg = new RegExp(regMul, 'i');
  204. match = reg.exec(title);
  205. if (match) {
  206. var mul = regZhn.indexOf(match[1]);
  207. if (mul == -1) mul = parseInt(match[1]);
  208. else if (mul === 0) mul = 2;
  209. if (lastMul != mul) {
  210. cap *= mul;
  211. tip += match[0].substr(1, match[0].length-1).trim();
  212. }
  213. }
  214. }
  215.  
  216. if (cap > 0) {
  217. var unitPrice = parseFloat(price) / cap;
  218. //如果单价>2000元或<0.5元,太大或太小不显示
  219. if (unitPrice > 2000 || unitPrice < 0.5) return null;
  220. else return {
  221. capacity: Math.round(cap * 10000) / 10000,
  222. unit: un,
  223. price: Math.round(unitPrice * 100) / 100,
  224. tip: tip.trim()
  225. };
  226. } else return null;
  227. }

QingJ © 2025

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