🏠 Home 

Greasy Fork is available in English.

炼丹炉-品牌排行

炼丹炉扩展工具

  1. // ==UserScript==
  2. // @name 炼丹炉-品牌排行
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.2
  5. // @description 炼丹炉扩展工具
  6. // @author siji-Xian
  7. // @match *://www.huo1818.com/app/jd/market/rank/brand?*
  8. // @icon https://cdn.zhiyitech.cn/material/4efba8e6ba2cf8883526fce8b21eac28
  9. // @license MIT
  10. // @require https://cdn.jsdelivr.net/npm/xlsx@0.17.1/dist/xlsx.full.min.js
  11. // @require https://greasyfork.org/scripts/455576-qmsg/code/Qmsg.js?version=1122361
  12. // ==/UserScript==
  13. (function () {
  14. "use strict";
  15. var new_element = document.createElement("link");
  16. new_element.setAttribute("rel", "stylesheet");
  17. new_element.setAttribute("href", "https://qmsg.refrain.xyz/message.min.css");
  18. document.body.appendChild(new_element);
  19. const button = document.createElement("div");
  20. button.textContent = "导出数据";
  21. Object.assign(button.style, {
  22. height: "34px",
  23. lineHeight: "var(--line-height, 34px)",
  24. alignItems: "center",
  25. color: "white",
  26. background: "linear-gradient(90deg, rgba(0, 239, 253), rgba(64, 166, 254))",
  27. borderRadius: "5px",
  28. marginLeft: "10px",
  29. fontSize: "13px",
  30. padding: "0 10px",
  31. cursor: "pointer",
  32. fontWeight: "500",
  33. });
  34. button.addEventListener("click", urlClick);
  35. function appendDoc() {
  36. const likeComment = document.querySelector(".fuui-row._title_1u19s_8");
  37. if (likeComment) {
  38. likeComment.append(button);
  39. return;
  40. }
  41. setTimeout(appendDoc, 1000);
  42. }
  43. appendDoc();
  44. //message.js
  45. let loadingMsg = null;
  46. //目标数据
  47. let target_data = null;
  48. (function listen() {
  49. var origin = {
  50. open: XMLHttpRequest.prototype.open,
  51. send: XMLHttpRequest.prototype.send,
  52. };
  53. XMLHttpRequest.prototype.open = function (a, b) {
  54. this.addEventListener("load", replaceFn);
  55. origin.open.apply(this, arguments);
  56. };
  57. XMLHttpRequest.prototype.send = function (a, b) {
  58. origin.send.apply(this, arguments);
  59. };
  60. function replaceFn(obj) {
  61. if (
  62. this?.responseURL?.slice(0, 36) ==
  63. "https://www.huo1818.com/backend-api/huo1818-olap-jd/industry/rank/brand-list"
  64. ) {
  65. target_data = JSON.parse(obj?.target?.response);
  66. }
  67. }
  68. })();
  69. //query参数获取
  70. function getQueryVariable(variable) {
  71. var query = window.location.search.substring(1);
  72. var vars = query.split("&");
  73. for (var i = 0; i < vars.length; i++) {
  74. var pair = vars[i].split("=");
  75. if (pair[0] == variable) {
  76. return pair[1];
  77. }
  78. }
  79. return false;
  80. }
  81. var myHeaders = new Headers();
  82. myHeaders.append("authority", "www.huo1818.com");
  83. myHeaders.append("accept", "*/*");
  84. myHeaders.append("accept-language", "zh-CN,zh;q=0.9");
  85. myHeaders.append("client", "web");
  86. myHeaders.append("group", "2");
  87. myHeaders.append("authorization", localStorage.getItem("__t"));
  88. myHeaders.append("name", "%E5%93%81%E7%89%8C%E6%8E%92%E8%A1%8C-%E8%A1%8C%E4%B8%9A%E5%88%86%E6%9E%90-%E7%82%BC%E4%B8%B9%E7%82%89");
  89. myHeaders.append("project", "huo");
  90. myHeaders.append("sec-ch-ua", "\"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"");
  91. myHeaders.append("sec-ch-ua-mobile", "?0");
  92. myHeaders.append("sec-ch-ua-platform", "\"macOS\"");
  93. myHeaders.append("sec-fetch-dest", "empty");
  94. myHeaders.append("sec-fetch-mode", "cors");
  95. myHeaders.append("sec-fetch-site", "same-origin");
  96. myHeaders.append("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
  97. const getRequestOptions = {
  98. method: "GET",
  99. headers: myHeaders,
  100. redirect: "follow",
  101. };
  102. async function fetchFun(url, data, requestOptions = getRequestOptions) {
  103. const params = new URLSearchParams(data).toString();
  104. try {
  105. const response = await fetch(`${url}?${params}`, requestOptions);
  106. if (response.ok) {
  107. const r###lt = await response.json();
  108. return r###lt;
  109. } else {
  110. throw new Error(`Fetch failed: ${response.status}`);
  111. }
  112. } catch (error) {
  113. loadingMsg.close();
  114. Qmsg.error({
  115. content: `网络请求错误: ${error.message}`,
  116. timeout: 5000,
  117. });
  118. throw error;
  119. }
  120. }
  121. async function getData(date) {
  122. const targetPromise = await fetchFun(
  123. "https://www.huo1818.com/backend-api/huo1818-olap-jd/industry/rank/brand-list",
  124. {
  125. orderField:'saleVolume',
  126. orderType:'desc',
  127. pageNo:getQueryVariable("pageNo"),
  128. pageSize:20,
  129. date,
  130. dateGroupType:"MONTH_GROUP",
  131. categoryId:getQueryVariable("catId"),
  132. }
  133. );
  134. return {date,value:targetPromise};
  135. }
  136. function exportToExcel(dataArray, sheetNames, headerAliases, fileName = "output.xlsx") {
  137. const workbook = XLSX.utils.book_new();
  138. // 遍历每个 Sheet
  139. dataArray.forEach((sheetData, index) => {
  140. // 获取当前 Sheet 的字段名数组
  141. const headers = Object.keys(sheetData.value[0]);
  142. // 创建工作表
  143. const sheet = XLSX.utils.json_to_sheet(sheetData.value, { header: headers});
  144. // 替换表头别名
  145. headers.forEach((header, columnIndex) => {
  146. if (headerAliases[header]) {
  147. sheet[XLSX.utils.encode_cell({ r: 0, c: columnIndex })].v = headerAliases[header];
  148. }
  149. });
  150. // 使用提供的 Sheet 名称或默认名称
  151. const sheetName = sheetNames[index] || `Sheet${index + 1}`;
  152. // 将工作表添加到工作簿
  153. XLSX.utils.book_append_sheet(workbook, sheet, sheetName);
  154. });
  155. // 将工作簿保存为 Excel 文件
  156. XLSX.writeFile(workbook, fileName);
  157. loadingMsg.close();
  158. }
  159. let contrast = {
  160. "brandId":"品牌ID",
  161. "brandName":"品牌名称",
  162. "saleVolume":"销量",
  163. "saleVolumeMomRatio":"销量环比",
  164. "saleAmount":"销售额",
  165. "saleAmountMomRatio":"销售额环比",
  166. "shopCount":"热销店铺数",
  167. "saleSkuCount":"动销SKU数"
  168. };
  169. async function urlClick() {
  170. loadingMsg = Qmsg.loading("正在导出,请勿重复点击!");
  171. let dates = ['202211','202212','202301','202302','202303','202304','202305','202306','202307','202308','202309','202310','202311'];
  172. let fetchData = [];
  173. async function fetchDataWithDelay() {
  174. for (const date of dates) {
  175. let r###lt = await getData(date);
  176. fetchData.push(r###lt);
  177. // 设置定时器,增加网络请求间隔,例如每隔500毫秒
  178. await delay(500);
  179. }
  180. }
  181. // 延迟函数
  182. function delay(ms) {
  183. return new Promise(resolve => setTimeout(resolve, ms));
  184. }
  185. // 调用包含定时器的数据获取函数
  186. await fetchDataWithDelay(); // 使用 await 确保 fetchDataWithDelay 执行完毕
  187. let data = fetchData.map(v => {
  188. return {
  189. date: v.date,
  190. value: v.value.r###lt.data.map(t=>{
  191. return {...t,saleAmount:t.saleAmount/100}
  192. })
  193. };
  194. });
  195. let fileName = '品牌排行' + document.querySelectorAll(".fuui-select-display--single-text")[0].innerHTML + "-" + document.querySelectorAll(".fuui-select-display--single-text")[1].innerHTML + "-" + document.querySelectorAll(".fuui-select-display--single-text")[2].innerHTML;
  196. loadingMsg = Qmsg.loading("正在导出,请勿重复点击!");
  197. exportToExcel(data, dates, contrast, `${fileName}.xlsx`);
  198. }
  199. })();