炼丹炉-行业品类

炼丹炉扩展工具

// ==UserScript==
// @name         炼丹炉-行业品类
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  炼丹炉扩展工具
// @author       siji-Xian
// @match        *://www.huo1818.com/app/industry/detail?*
// @icon         https://cdn.zhiyitech.cn/material/4efba8e6ba2cf8883526fce8b21eac28
// @license      MIT
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js
// @require      https://greasyfork.org/scripts/455576-qmsg/code/Qmsg.js?version=1122361
// ==/UserScript==

(function () {
  "use strict";
  var new_element = document.createElement("link");
  new_element.setAttribute("rel", "stylesheet");
  new_element.setAttribute("href", "https://qmsg.refrain.xyz/message.min.css");
  document.body.appendChild(new_element);

  const button = document.createElement("div");
  button.textContent = "导出数据";
  Object.assign(button.style, {
    height: "34px",
    lineHeight: "var(--line-height, 34px)",
    alignItems: "center",
    color: "white",
    background: "linear-gradient(90deg, rgba(0, 239, 253), rgba(64, 166, 254))",
    borderRadius: "5px",
    marginLeft: "10px",
    fontSize: "13px",
    padding: "0 10px",
    cursor: "pointer",
    fontWeight: "500",
  });
  button.addEventListener("click", urlClick);

  function appendDoc() {
    const likeComment = document.querySelector(".fuui-row.undefined");
    if (likeComment) {
      likeComment.append(button);
      return;
    }
    setTimeout(appendDoc, 1000);
  }
  appendDoc();

  //message.js
  let loadingMsg = null;
  let loadingMsg1 = null;

  //目标数据
  let target_data = null;

  (function listen() {
    var origin = {
      open: XMLHttpRequest.prototype.open,
      send: XMLHttpRequest.prototype.send,
    };
    XMLHttpRequest.prototype.open = function (a, b) {
      this.addEventListener("load", replaceFn);
      origin.open.apply(this, arguments);
    };
    XMLHttpRequest.prototype.send = function (a, b) {
      origin.send.apply(this, arguments);
    };
    function replaceFn(obj) {
      if (
        this?.responseURL?.slice(0, 66) ==
        "https://www.huo1818.com/backend-api/huo1818-oltp/user/monitor/list"
      ) {
        target_data = JSON.parse(obj?.target?.response);
      }
    }
  })();

  var myHeaders = new Headers();
  myHeaders.append("authority", "www.huo1818.com");
  myHeaders.append("accept", "*/*");
  myHeaders.append("accept-language", "zh-CN,zh;q=0.9");
  myHeaders.append("client", "web");
  myHeaders.append("group", "2");
  myHeaders.append("authorization", localStorage.getItem("__t"));
  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");
  myHeaders.append("project", "huo");
  myHeaders.append("sec-ch-ua", "\"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"");
  myHeaders.append("sec-ch-ua-mobile", "?0");
  myHeaders.append("sec-ch-ua-platform", "\"macOS\"");
  myHeaders.append("sec-fetch-dest", "empty");
  myHeaders.append("sec-fetch-mode", "cors");
  myHeaders.append("sec-fetch-site", "same-origin");
  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");

  const getRequestOptions = {
    method: "GET",
    headers: myHeaders,
    redirect: "follow",
  };

  async function fetchFun(url, data, requestOptions = getRequestOptions) {
    const params = new URLSearchParams(data).toString();
    try {
      const response = await fetch(`${url}?${params}`, requestOptions);
      if (response.ok) {
        const result = await response.json();
        return result;
      } else {
        throw new Error(`Fetch failed: ${response.status}`);
      }
    } catch (error) {
      if (loadingMsg) loadingMsg.close();
      Qmsg.error({
        content: `网络请求错误: ${error.message}`,
        timeout: 5000,
      });
      throw error;
    }
  }

  async function getData(e,level) {
    if (level === 1) {
      const targetPromise = await fetchFun(
        "https://www.huo1818.com/backend-api/huo1818-olap/industry/overview/category-rank",
        {
          dateGroupType: 'MONTH_GROUP',
          date: 202403,
          bigCatId: e.bigCategoryId,
          cat1tId: e.cat1tId,
          catId: e.cat1tId,
          categoryId: e.cat1tId,
          platformId: ''
        }
      );
      let data = targetPromise.result.map(v=>{
        return {
          categoryName:v.categoryName,
          categoryId:v.categoryId,
          cat1tName:e.cat1tName,
          cat1tId:e.cat1tId
        }
      })
  
      return data;
    } else {
      const targetPromise = await fetchFun(
        "https://www.huo1818.com/backend-api/huo1818-olap/industry/common/category-selector",
        {
          categoryId: e.categoryId,
          categoryLevel: 2
        }
      );
        if (targetPromise.result.length) {
          let data = targetPromise.result.map(v=>{
            return {
              level3Name:v.categoryName,
              level3Id:v.categoryId,
              categoryName:e.categoryName,
              categoryId:e.categoryId,
              level1Name:e.cat1tName,
              level1Id:e.cat1tId
            }
          })
          return data;
        }else{
          return [{
            categoryName:e.categoryName,
            categoryId:e.categoryId,
            level1Name:e.cat1tName,
            level1Id:e.cat1tId
          }]
        }
    }
    
  }

  function exportToExcel(data, headerAliases, fileName = "output.xlsx") {
    // 获取字段名数组
    const headers = Object.keys(data[0]);
  
    // 创建工作表
    const sheet = XLSX.utils.json_to_sheet(data, { header: headers, skipHeader: true });
  
    // 替换表头别名
    headers.forEach((header, index) => {
      if (headerAliases[header]) {
        sheet[XLSX.utils.encode_cell({ r: 0, c: index })].v = headerAliases[header];
      }
    });

    // 创建工作簿
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, sheet, "Sheet1");
  
    // 将工作簿保存为 Excel 文件
    XLSX.writeFile(workbook, fileName);

    loadingMsg1.close();
  }

  
  let contrast = {
    "level1Name":"行业",
    "level1Id":"行业ID",
    "categoryName":"品类",
    "categoryId":"品类ID",
    "level3Name":"二级品类",
    "level3Id":"二级品类ID"
  };

  async function urlClick() {
    if (target_data) {
      loadingMsg = Qmsg.loading("正在导出,请勿重复点击!");
      let target_data_res = target_data.result.userMonitorList.map(v=>{
        return {
          cat1tName:v.cat1tName,
          cat1tId:v.cat1tId,
          bigCategoryId:v.bigCategoryId
        }
      })

      let fetchData = [];

     
      async function fetchDataWithDelay() {
        for (const item of target_data_res) {
          let result = await getData(item,1);
          fetchData.push(result);
    
          // 设置定时器,增加网络请求间隔,例如每隔500毫秒
          await delay(500);
        }
      }
    
      // 延迟函数
      function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
      }
    
      // 调用包含定时器的数据获取函数
      await fetchDataWithDelay(); // 使用 await 确保 fetchDataWithDelay 执行完毕

      let level2Data = fetchData.flat()

      loadingMsg.close()
      loadingMsg1 = Qmsg.loading(`数据较多,请耐心等待(共${level2Data.length}个接口,预计导出耗时${Math.floor(level2Data.length/60)}分钟)`);
  

      let fetchData2 = [];
  
      async function fetchDataWithDelay2() {
        for (const item of level2Data) {
          let result = await getData(item,2);
          fetchData2.push(result);
    
          // 设置定时器,增加网络请求间隔,例如每隔500毫秒
          await delay(500);
        }
      }
    
      // 调用包含定时器的数据获取函数
      await fetchDataWithDelay2(); // 使用 await 确保 fetchDataWithDelay2 执行完毕

      // console.log(fetchData2.flat());

      let data = fetchData2.flat()

      let fileName = '品牌排行';
      exportToExcel(data, contrast, `${fileName}.xlsx`);
    } else {
      loadingMsg = Qmsg.error("数据加载失败,请重试");
    }
  }
  
})();