保存fetch和xhr

自动保存/备份 fetch/xhr/ajax请求响应的脚本,导出为json文件,可以用于多种用途,比如说自动保存浏览过的b站视频评论、收藏夹、知乎回答、知乎评论、知乎收藏、小红书评论、百度网盘文件列表等等。初始目的为弥补https://archive.org/无法保存动态加载的网页的问题。而且f12 network export har无法仅保存某些请求,且步骤比较繁琐,无法自动。

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         保存fetch和xhr
// @namespace    http://tampermonkey.net/
// @version      2024-04-08
// @description  自动保存/备份 fetch/xhr/ajax请求响应的脚本,导出为json文件,可以用于多种用途,比如说自动保存浏览过的b站视频评论、收藏夹、知乎回答、知乎评论、知乎收藏、小红书评论、百度网盘文件列表等等。初始目的为弥补https://archive.org/无法保存动态加载的网页的问题。而且f12 network export har无法仅保存某些请求,且步骤比较繁琐,无法自动。
// @author       You
// @match        https://www.zhihu.com/collection/*
// @match        https://www.zhihu.com/people/*
// @match        https://*.bilibili.com/*
// @match        https://cloud.heytap.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=zhihu.com
// @require https://update.greasyfork.org/scripts/472943/1320613/Itsnotlupus%27%20MiddleMan.js
// @run-at document-start
// @grant    GM_setValue
// @grant    GM_listValues
// @grant    GM_getValue
// @grant    GM_deleteValue
// @grant    GM_notification
// @license      LGPLv3
// ==/UserScript==



newFunction("https://www.zhihu.com/api/v4/*");
newFunction("https://api.bilibili.com/x/v3/*");
newFunction("https://api.bilibili.com/x/space/wbi/arc/search*");
newFunction("https://ck-rest-cn.heytap.com/albumpc/v3/albumDetail");
newFunction("https://api.bilibili.com/x/v2/reply/wbi/*");



function newFunction(hookUrl) {
	middleMan.addHook(hookUrl, {
		async responseHandler(request, response, error) {
			// console.log("snooped on response:",request, response, error);
			// console.log(await response?.json())
			// let jsonString = JSON.stringify(await response?.json());
			let jsonString = await response.json(); // 可以是对象不转换为字符串


			// gpt,使用GM_setValue将response.url作为key把json存储起来
			if (jsonString && response.url) {
				GM_setValue(response.url, jsonString);
			}
		}
	});
}

// gpt,使用GM_listValues和GM_getValue函数,获取所有保存的键值对为一个对象
// 获取所有保存的键值对并组成一个对象
function savedJson() {
	let savedData = {};
	let keys = GM_listValues();
	keys.forEach(key => {
		let value = GM_getValue(key);
		savedData[key] = value;
	});
	// 将savedData对象下载为一个json文件
	downloadFunc(savedData)
}

function downloadFunc(params) {
	// 创建一个 JSON 字符串
	let jsonData = JSON.stringify(params);
	// 创建一个新的 Blob 对象
	let blob = new Blob([jsonData], {
		type: 'application/json'
	});
	// 创建一个临时 URL,用于下载 JSON 文件
	let url = URL.createObjectURL(blob);
	// 创建一个隐藏的链接
	let a = document.createElement('a');
	a.style.display = 'none';
	a.href = url;

	let currentDate = new Date(+new Date() + 8 * 3600 * 1000).toISOString().slice(0, 19).replace(/[-T:/]/g, ''); // 获取当前日期和时间
	a.download = 'savedResponse_' + currentDate + '.json'; // 文件名包含当前日期和时间 // gpt,'savedResponse这里加上当前的日期和时间.json'


	document.body.appendChild(a);

	a.onclick = (e) => {
		e.stopPropagation();
	}
	// 触发点击事件来下载文件
	a.click();
	// 释放 URL 对象
	URL.revokeObjectURL(url);
}


// clearSavedData 函数用于执行清空操作
function clearSavedData() {
	// 获取所有保存的键值对
	let keys = GM_listValues();

	// 遍历所有键并删除对应的值
	keys.forEach(key => {
		GM_deleteValue(key);
	});

	// 提示用户清空完成(可选)
	// alert('保存的响应数据已清空');
	GM_notification({
		title: '数据已清空',
		text: '保存的数据已清空',
		timeout: 3000 // 通知显示时间,单位为毫秒
	});
}

let top = 0
// gpt,在页面右上方添加一个按钮,点击这个按钮,调用savedJson函数
function addButton(textContent, listener) {
	// 创建一个按钮
	let button = document.createElement('button');

	button.textContent = textContent;
	button.style.position = 'fixed';
	button.style.top = top + 50 + 'px';
	top += 50;
	button.style.right = '10px';
	button.style.zIndex = '9999';

	// 添加点击事件
	button.addEventListener('click', listener);

	// 添加鼠标悬停和离开事件处理
	button.addEventListener('mouseenter', function () {
		button.style.backgroundColor = '#ddd'; // 鼠标悬停时的颜色
	});

	button.addEventListener('mouseleave', function () {
		button.style.backgroundColor = ''; // 鼠标离开时恢复原色
	});

	// 将按钮添加到页面
	document.body.appendChild(button);

	// gpt,给这个按钮添加鼠标悬停变色的效果
}


// setTimeout(addButton('下载保存的所有请求数据', savedJson), 3000);
setTimeout(() => addButton('下载保存的所有请求数据', savedJson), 3000);
setTimeout(() => addButton('清空', clearSavedData), 3000);

console.log(123);