// ==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();
}
})();