在网页加载前和加载后执行自定义代码

117 阅读3分钟

主要是“加载前”,如果单单只是加载后,那么可以通过注入js的方式。

实现方式1:使用浏览器扩展(推荐、最干净)

image.png

实现方式2:使用油猴(其实也还是插件的方式,只不过是依附于油猴这个插件,而自己不用写插件):

已经尝试过,此处配置不论是baidu.com还是zhihu.com都可以正常执行

事后代码(注意此处事后的写在了前面):

// ==UserScript==
// @name         Run Custom JS After Load
// @namespace    http://tampermonkey.net/
// @version      2025-09-23
// @description  try to take over the world!
// @author       wenzd
// @run-at       document-end
// @match        *://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    console.log("Custom JS running after page load!");
    // 在这里添加你的自定义代码
    //debugger;
    window.xFuck = "Hello from Tampermonkey!";
    // Your code here...

// === Step 1: 记录 baseline ===
if (!window.__baselineGlobals) {
    //【西西 2025-09-23 152258】不应该走到这一步
    debugger;
    window.__baselineGlobals = {};

    Object.getOwnPropertyNames(window).forEach(name => {
        try {
            let desc = Object.getOwnPropertyDescriptor(window, name);
            // 保存 descriptor 和 value(如果是函数/对象只保存引用,不做深拷贝)
            window.__baselineGlobals[name] = {
                desc,
                value: window[name]
            };
        } catch (e) {
            // 某些属性可能抛异常(如跨域对象),忽略
        }
    });

    console.log("✅ 已保存 window 初始全局属性快照。刷新页面后再次运行此 Snippet 进行对比。");

} else {
    //【西西 2025-09-23 152304】走到这一步是符合预期的
    debugger;
    // === Step 2: 对比 ===
    let before = window.__baselineGlobals;
    let afterNames = Object.getOwnPropertyNames(window);

    let added = afterNames.filter(k => !before[k]);
    let removed = Object.keys(before).filter(k => !afterNames.includes(k));

    let modified = [];
    Object.keys(before).forEach(name => {
        if (afterNames.includes(name)) {
            try {
                let currentDesc = Object.getOwnPropertyDescriptor(window, name);
                let baseline = before[name];

                // 判断 descriptor 是否不同
                let descChanged = JSON.stringify(currentDesc) !== JSON.stringify(baseline.desc);

                // 判断 value 是否被替换(引用对比,不是深度内容对比)
                let valueChanged = window[name] !== baseline.value;

                if (descChanged || valueChanged) {
                    modified.push({
                        name,
                        descChanged,
                        valueChanged,
                        oldType: typeof baseline.value,
                        newType: typeof window[name]
                    });
                }
            } catch (e) {
                // 有些 getter 会报错,忽略
            }
        }
    });

    console.group("🌍 Window 全局对象变更情况");
    console.log("➕ 新增的全局变量:", added);
    console.log("➖ 被移除的全局变量:", removed);
    console.log("✏️ 被重写/修改的全局变量:", modified);
    console.groupEnd();

    // 清理快照,方便下次重新记录
    delete window.__baselineGlobals;
}})();

事前代码:

`// ==UserScript== // @name Run Custom JS Before Load // @namespace tampermonkey.net/ // @version 2025-09-23 // @description try to take over the world! // @author wenzd // @run-at document-start // @match :///* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // ==/UserScript==

(function() { 'use strict'; console.log("Custom JS running before page load!"); // 在这里添加你的自定义代码 //debugger; window.xFuck = "Hello from Tampermonkey!"; // Your code here...

// === Step 1: 记录 baseline ===
if (!window.__baselineGlobals) {
    //【西西 2025-09-23 152304】走到这一步是符合预期的
    debugger;
    window.__baselineGlobals = {};

    Object.getOwnPropertyNames(window).forEach(name => {
        try {
            let desc = Object.getOwnPropertyDescriptor(window, name);
            // 保存 descriptor 和 value(如果是函数/对象只保存引用,不做深拷贝)
            window.__baselineGlobals[name] = {
                desc,
                value: window[name]
            };
        } catch (e) {
            // 某些属性可能抛异常(如跨域对象),忽略
        }
    });

    console.log("✅ 已保存 window 初始全局属性快照。刷新页面后再次运行此 Snippet 进行对比。");

} else {
    //【西西 2025-09-23 152258】不应该走到这一步
    debbugger;
    // === Step 2: 对比 ===
    let before = window.__baselineGlobals;
    let afterNames = Object.getOwnPropertyNames(window);

    let added = afterNames.filter(k => !before[k]);
    let removed = Object.keys(before).filter(k => !afterNames.includes(k));

    let modified = [];
    Object.keys(before).forEach(name => {
        if (afterNames.includes(name)) {
            try {
                let currentDesc = Object.getOwnPropertyDescriptor(window, name);
                let baseline = before[name];

                // 判断 descriptor 是否不同
                let descChanged = JSON.stringify(currentDesc) !== JSON.stringify(baseline.desc);

                // 判断 value 是否被替换(引用对比,不是深度内容对比)
                let valueChanged = window[name] !== baseline.value;

                if (descChanged || valueChanged) {
                    modified.push({
                        name,
                        descChanged,
                        valueChanged,
                        oldType: typeof baseline.value,
                        newType: typeof window[name]
                    });
                }
            } catch (e) {
                // 有些 getter 会报错,忽略
            }
        }
    });

    console.group("🌍 Window 全局对象变更情况");
    console.log("➕ 新增的全局变量:", added);
    console.log("➖ 被移除的全局变量:", removed);
    console.log("✏️ 被重写/修改的全局变量:", modified);
    console.groupEnd();

    // 清理快照,方便下次重新记录
    delete window.__baselineGlobals;
}})();