使用 Greasemonkey/Tampermonkey 保存数据供以后检索
Save data using Greasemonkey/Tampermonkey for later retrieval
我正在从事一个需要网站数据的项目。该数据的问题在于它被组织成许多不同的网页,在 URL 中带有序列号。为了解决这个问题,我在 Tampermonkey 中编写了一个简单的脚本,它循环访问这些页面并获取脚本中字符串变量中的数据。
现在真正的问题来了,我该如何存储这些数据。我知道我无法在我的 PC 上写入文件,但数据是否可以显示在浏览器的单独选项卡上,以便我可以在循环完成后将其复制并粘贴到本地文件中?我希望在每个循环中将一个字符串附加到存储中
我不想使用 GM_setValue
,因为我想要原始文本格式的数据(如 .txt
文件)
但是,如果它可以在不使用外部库的情况下直接写入我 PC 上的文件,那将是首选。
I know I can't write to a file on my PC
这里有一些好消息要告诉您:是的,您可以!
var a = document.createElement("a");
a.href = "data:text,Hello World!"; //content
a.download = "Hello.txt"; //file name
a.click();
http://jsfiddle.net/DerekL/jgfhwfL0/
首先打开您的本地主机页面,master.html
(http://localhost:8080/master.html
):
<html>
<head>
<script>
window.addEventListener("load", function(){
//This is just like working with threads but in JavaScript
if(location.search.length){
//receiver
var query = decodeURIComponent(location.search.slice(1));
var data = JSON.parse(query).value;
//handle data
localStorage.storage = +localStorage.storage + data;
location.href = "about:blank"; //exit
}else{
//master
sum = document.getElementById("sum");
sum.innerText = localStorage.storage = "0";
window.addEventListener("storage", function(){
//data received from receiver
sum.innerText = localStorage.storage;
});
}
});
</script>
</head>
<body>
Sum: <span id="sum"></span>
</body>
</html>
然后你就可以在任何网页中开始向它发送数据了:
var frame = document.createElement("iframe");
frame.src = 'http://localhost:8080/master.html?{"value":90}'; //port 8080
document.body.appendChild(frame);
总和计数器应在收到数据后自动更新。
一种方法是 运行 本地主机 HTTP 服务器,公开路由并使用它们来读取和写入文件,并且通常会执行用户脚本所需的所有 back-end 操作。
这是使用 Node 17 和 Express 的简单概念回显证明,但同样可以使用您喜欢的任何 back-end 技术来完成。
server.js
:
const cors = require("cors"); // "^2.8.5"
const express = require("express"); // "^4.18.1"
const fs = require("fs").promises;
const path = require("path");
const dataFile = "data.json";
const app = express();
app
.set("port", process.env.PORT || 5000)
.use(cors())
.use(express.json())
.get("/", (req, res) => {
fs.readFile(path.join(__dirname, dataFile))
.then(file => res.send(file.toString()))
.catch(err => res.status(404).send(err.message));
})
.post("/", (req, res) => {
const p = path.join(__dirname, dataFile);
fs.writeFile(p, JSON.stringify(req.body))
.then(file => res.sendStatus(200))
.catch(err => res.status(400).send(err.message));
})
.listen(app.get("port"), () =>
console.log(`server listening on port ${app.get("port")}`)
);
Tampermonkey 脚本:
const url = "http://localhost:5000";
const writeData = payload =>
fetch(url, {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) {
throw Error(response.status);
}
});
const readData = () =>
fetch(url)
.then(response => {
if (!response.ok) {
throw Error(response.status);
}
return response.json();
});
writeData({hello: "world"})
.then(readData)
.then(data => console.log(data)) // => {hello: 'world'}
.catch(err => console.error(err));
除了启用 cross-origin 访问和从用户脚本而不是典型的客户端(如网页或应用程序)发送请求的新颖性之外,这里没有什么特别的。
请谨慎使用,因为这会将本地文件系统暴露给未知网站上的潜在恶意脚本运行。
我正在从事一个需要网站数据的项目。该数据的问题在于它被组织成许多不同的网页,在 URL 中带有序列号。为了解决这个问题,我在 Tampermonkey 中编写了一个简单的脚本,它循环访问这些页面并获取脚本中字符串变量中的数据。
现在真正的问题来了,我该如何存储这些数据。我知道我无法在我的 PC 上写入文件,但数据是否可以显示在浏览器的单独选项卡上,以便我可以在循环完成后将其复制并粘贴到本地文件中?我希望在每个循环中将一个字符串附加到存储中
我不想使用 GM_setValue
,因为我想要原始文本格式的数据(如 .txt
文件)
但是,如果它可以在不使用外部库的情况下直接写入我 PC 上的文件,那将是首选。
I know I can't write to a file on my PC
这里有一些好消息要告诉您:是的,您可以!
var a = document.createElement("a");
a.href = "data:text,Hello World!"; //content
a.download = "Hello.txt"; //file name
a.click();
http://jsfiddle.net/DerekL/jgfhwfL0/
首先打开您的本地主机页面,master.html
(http://localhost:8080/master.html
):
<html>
<head>
<script>
window.addEventListener("load", function(){
//This is just like working with threads but in JavaScript
if(location.search.length){
//receiver
var query = decodeURIComponent(location.search.slice(1));
var data = JSON.parse(query).value;
//handle data
localStorage.storage = +localStorage.storage + data;
location.href = "about:blank"; //exit
}else{
//master
sum = document.getElementById("sum");
sum.innerText = localStorage.storage = "0";
window.addEventListener("storage", function(){
//data received from receiver
sum.innerText = localStorage.storage;
});
}
});
</script>
</head>
<body>
Sum: <span id="sum"></span>
</body>
</html>
然后你就可以在任何网页中开始向它发送数据了:
var frame = document.createElement("iframe");
frame.src = 'http://localhost:8080/master.html?{"value":90}'; //port 8080
document.body.appendChild(frame);
总和计数器应在收到数据后自动更新。
一种方法是 运行 本地主机 HTTP 服务器,公开路由并使用它们来读取和写入文件,并且通常会执行用户脚本所需的所有 back-end 操作。
这是使用 Node 17 和 Express 的简单概念回显证明,但同样可以使用您喜欢的任何 back-end 技术来完成。
server.js
:
const cors = require("cors"); // "^2.8.5"
const express = require("express"); // "^4.18.1"
const fs = require("fs").promises;
const path = require("path");
const dataFile = "data.json";
const app = express();
app
.set("port", process.env.PORT || 5000)
.use(cors())
.use(express.json())
.get("/", (req, res) => {
fs.readFile(path.join(__dirname, dataFile))
.then(file => res.send(file.toString()))
.catch(err => res.status(404).send(err.message));
})
.post("/", (req, res) => {
const p = path.join(__dirname, dataFile);
fs.writeFile(p, JSON.stringify(req.body))
.then(file => res.sendStatus(200))
.catch(err => res.status(400).send(err.message));
})
.listen(app.get("port"), () =>
console.log(`server listening on port ${app.get("port")}`)
);
Tampermonkey 脚本:
const url = "http://localhost:5000";
const writeData = payload =>
fetch(url, {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) {
throw Error(response.status);
}
});
const readData = () =>
fetch(url)
.then(response => {
if (!response.ok) {
throw Error(response.status);
}
return response.json();
});
writeData({hello: "world"})
.then(readData)
.then(data => console.log(data)) // => {hello: 'world'}
.catch(err => console.error(err));
除了启用 cross-origin 访问和从用户脚本而不是典型的客户端(如网页或应用程序)发送请求的新颖性之外,这里没有什么特别的。
请谨慎使用,因为这会将本地文件系统暴露给未知网站上的潜在恶意脚本运行。