通过 greasemonkey 脚本动态替换页面元素(甚至 post 页面加载)
Replacing page elements dynamically through a greasemonkey script (even post page load)
我有以下 javascript 功能:
function actionFunction() {
let lookup_table = {
'imageurl1': "imageurl2",
};
for (let image of document.getElementsByTagName("img")) {
for (let query in lookup_table) {
if (image.src == query) {
image.src = lookup_table[query];
}
}
}
}
我希望它即使在页面完全加载后也能正常工作(换句话说,使用动态生成的 html 元素出现 post- 由页面的 js 加载)。
它可以是 运行 每 x 秒的函数或当在页面中检测到某个元素 xpath 时,或者每次在浏览器中加载某个图像 url 时(这是我的主要目标)。
如何使用 javascript + greasemonkey 实现此目的?
谢谢。
您是否尝试过 运行在浏览器的终端中运行您的代码,看看它是否可以在不涉及 greasemonkey 的情况下运行?
关于你的问题 - 你可以使用 setInterval 来 运行 每 x 时间给定的代码,或者你可以使用 MutationObserver 来监视网页 dom 的变化。在我看来 setInterval 足以胜任这项工作,您可以在以后尝试学习 MutationObserver 的工作原理。
所以重写你的代码:
// arrow function - doesn't lose this value and execution context
// setInterval executes in a different context than the enclosing scope which makes functions lose this reference
// which results in being unable to access the document object
// and also window as they all descend from global scope which is lost
// you also wouldn't be able to use console object
// fortunately we have arrow functions
// because arrow functions establish this based on the scope the arrow function is defined within
// which in most cases is global scope
// so we have access to all objects and their methods
const doImageLookup = () => {
const lookup_table = {
'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png': 'https://www.google.com/logos/doodles/2022/gama-pehlwans-144th-birthday-6753651837109412-2x.png',
};
const imgElementsCollection = document.getElementsByTagName('img');
[...imgElementsCollection].forEach((imgElement) => {
Object.entries(lookup_table).forEach(([key, value]) => {
const query = key; // key and value describe object's properties
const replacement = value; // here object is used in an unusual way, i would advise to use array of {query, replacement} objects instead
if (imgElement.src === query) {
imgElement.src = replacement;
}
});
});
};
const FIVE_MINUTES = 300000; // ms
setInterval(doImageLookup, FIVE_MINUTES);
您可以通过跟踪 img 计数并仅在其数量增加时执行 imageLookop 来制作更复杂的版本。这将是一个很大的优化,可以让您 运行 更频繁地查询(尽管 5 分钟是相当长的间隔,请根据需要进行调整)。
我有以下 javascript 功能:
function actionFunction() {
let lookup_table = {
'imageurl1': "imageurl2",
};
for (let image of document.getElementsByTagName("img")) {
for (let query in lookup_table) {
if (image.src == query) {
image.src = lookup_table[query];
}
}
}
}
我希望它即使在页面完全加载后也能正常工作(换句话说,使用动态生成的 html 元素出现 post- 由页面的 js 加载)。
它可以是 运行 每 x 秒的函数或当在页面中检测到某个元素 xpath 时,或者每次在浏览器中加载某个图像 url 时(这是我的主要目标)。
如何使用 javascript + greasemonkey 实现此目的? 谢谢。
您是否尝试过 运行在浏览器的终端中运行您的代码,看看它是否可以在不涉及 greasemonkey 的情况下运行?
关于你的问题 - 你可以使用 setInterval 来 运行 每 x 时间给定的代码,或者你可以使用 MutationObserver 来监视网页 dom 的变化。在我看来 setInterval 足以胜任这项工作,您可以在以后尝试学习 MutationObserver 的工作原理。
所以重写你的代码:
// arrow function - doesn't lose this value and execution context
// setInterval executes in a different context than the enclosing scope which makes functions lose this reference
// which results in being unable to access the document object
// and also window as they all descend from global scope which is lost
// you also wouldn't be able to use console object
// fortunately we have arrow functions
// because arrow functions establish this based on the scope the arrow function is defined within
// which in most cases is global scope
// so we have access to all objects and their methods
const doImageLookup = () => {
const lookup_table = {
'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png': 'https://www.google.com/logos/doodles/2022/gama-pehlwans-144th-birthday-6753651837109412-2x.png',
};
const imgElementsCollection = document.getElementsByTagName('img');
[...imgElementsCollection].forEach((imgElement) => {
Object.entries(lookup_table).forEach(([key, value]) => {
const query = key; // key and value describe object's properties
const replacement = value; // here object is used in an unusual way, i would advise to use array of {query, replacement} objects instead
if (imgElement.src === query) {
imgElement.src = replacement;
}
});
});
};
const FIVE_MINUTES = 300000; // ms
setInterval(doImageLookup, FIVE_MINUTES);
您可以通过跟踪 img 计数并仅在其数量增加时执行 imageLookop 来制作更复杂的版本。这将是一个很大的优化,可以让您 运行 更频繁地查询(尽管 5 分钟是相当长的间隔,请根据需要进行调整)。