接口请求响应监听器

监听指定接口的请求参数和返回数据

目前為 2025-05-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name         接口请求响应监听器
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  监听指定接口的请求参数和返回数据
// @license MIT
// @match        *://*.taobao.com/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.5/xlsx.full.min.js
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

(function () {
  "use strict";

  // 核心创建方法
  var csv = [];
  // 核心导出方法
  const exportToExcel = (data) => {
    // 转换数据为工作表格式
    const worksheet = XLSX.utils.json_to_sheet(data, {
      header: Object.keys(data[0]), // 自动提取表头
      skipHeader: false,
    });

    // 创建工作簿
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, "数据报表");

    // 生成文件(文件名带时间戳)
    const timestamp = new Date().toISOString().slice(0, 16).replace(/:/g, "-");
    XLSX.writeFile(workbook, `导出数据_${timestamp}.xlsx`);
  };

  // 创建悬浮控制面板
  const createControlPanel = () => {
    const panel = document.createElement("div");
    panel.style = `
            position: fixed;
            bottom: 50px;
            right: 20px;
            z-index: 99999;
            background: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            min-width: 180px;
        `;

    const btn = document.createElement("button");
    btn.textContent = "启动监听";
    btn.style = `
            padding: 8px 15px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            width: 100%;
        `;

    const status = document.createElement("div");
    status.textContent = "状态:未监听";
    status.style = "margin-top:10px;font-size:12px;color:#666;";
    // 创建浮动按钮
    const download = document.createElement("button");
    Object.assign(download.style, {
    //   position: "fixed",
    //   bottom: "20px",
    //   right: "20px",
      padding: "8px 15px",
      backgroundColor: "#4CAF50",
      color: "white",
      border: "none",
      borderRadius: "4px",
      cursor: "pointer",
      zIndex: 99999,
    });
    download.textContent = "导出Excel";

    // 点击事件处理
    download.addEventListener("click", () => {
      try {
        exportToExcel(csv);
        download.style.backgroundColor = "#45a049";
        setTimeout(() => (download.style.backgroundColor = "#4CAF50"), 1000);

      } catch (e) {
        alert("导出失败: " + e.message);
      }
    });
    const n = document.createElement("div");
    n.className = "countN"
    n.textContent = `当前抓取数据:${csv.length}条`
    //  // 插入按钮
    //  document.body.appendChild();

    panel.append(btn, status, download,n);
    return { panel, btn, status };
  };

  // 主逻辑
  const main = () => {
    const { panel, btn, status } = createControlPanel();
    document.body.appendChild(panel);

    let isMonitoring = false;
    const targetAPI =
      "mtop.taobao.guangguang.matchmaking.material.item.collect.query";

    // 保存原始方法
    const nativeOpen = unsafeWindow.XMLHttpRequest.prototype.open;
    const nativeSend = unsafeWindow.XMLHttpRequest.prototype.send;
    const nativeFetch = unsafeWindow.fetch;

    // 重写XMLHttpRequest
    unsafeWindow.XMLHttpRequest.prototype.open = function (method, url) {
      this._requestURL = url; // 存储请求地址
      return nativeOpen.apply(this, arguments);
    };

    unsafeWindow.XMLHttpRequest.prototype.send = function (body) {
      if (isMonitoring && this._requestURL.includes(targetAPI)) {
        const requestData = {
          url: this._requestURL,
          method: this._method,
          params: body ? new URLSearchParams(body).toString() : null,
        };

        // 监听响应
        this.addEventListener("load", function () {
          try {
            const response = JSON.parse(this.responseText);
            console.groupCollapsed(`监听到接口 ${targetAPI}`);
            console.log("请求参数:", requestData);
            console.log("返回数据:", response);
            csv = csv.concat(response.data.data)
            document.querySelector('.countN').textContent = `当前抓取数据:${csv.length}条`
            console.groupEnd();
          } catch (e) {
            console.error("响应解析失败:", e);
          }
        });
      }
      return nativeSend.apply(this, arguments);
    };

    // 重写Fetch
    unsafeWindow.fetch = function (input, init) {
      const url = typeof input === "string" ? input : input.url;

      if (isMonitoring && url.includes(targetAPI)) {
        const requestData = {
          url,
          method: init?.method || "GET",
          params: init?.body ? new URLSearchParams(init.body).toString() : null,
        };

        return nativeFetch(input, init).then((response) => {
          response
            .clone()
            .json()
            .then((data) => {
              console.groupCollapsed(`监听到接口 ${targetAPI}`);
              console.log("请求参数:", requestData);
              console.log("返回数据:", data);
              console.groupEnd();
            });
          return response;
        });
      }
      return nativeFetch(input, init);
    };

    // 控制按钮交互
    btn.addEventListener("click", () => {
      if (isMonitoring) {
        console.log("已停止监听");
        csv = [];
        document.querySelector('.countN').textContent = `当前抓取数据:${csv.length}条`

      }
      isMonitoring = !isMonitoring;
      btn.textContent = isMonitoring ? "停止监听" : "启动监听";
      btn.style.background = isMonitoring ? "#4CAF50" : "#2196F3";
      status.textContent = `状态:${isMonitoring ? "监听中" : "未监听"}`;
    });
  };

  // 初始化
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", main);
  } else {
    main();
  }
})();

QingJ © 2025

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