Tampermonkey 篡改猴 建立第一個腳本

瀏覽網站時發現有些功能不夠好,除了安裝套件外,我們還可以自己動手修改,只要執行自訂的 JavaScript ,幾乎可以把網站改成任何樣式。

但是要怎麼樣執行腳本?每次都在 F12 的主控台執行嗎?
我們可以透過 Tampermonkey 這個瀏覽器擴充套件,他最主要的功能就是執行我們的 JavaScript,方便我們修改網頁,本篇就來示範撰寫 Tampermonkey 的腳本,實現自己需要的功能!

安裝 Tampermonkey 套件

開啟 Chrome 線上應用程式商店,點選右上角的「加到 Chrome」

點選「新增擴充功能」

FireFoxEdge 等瀏覽器也可以到各自的商店下載安裝。

建立第一個腳本

找到工具列上的 Tampermonkey 圖示,使用滑鼠左鍵點擊後再點擊選單的「新增腳本」

就會出現 Tampermonkey 內建的編輯器,在這裡就可以完成腳本的開發。

預設內容如下:
    
// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2023-12-15
// @description  try to take over the world!
// @author       You
// @match        http://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
})();
    

==UserScript== 是 Tampermonkey 腳本的資訊區塊,各參數用途如下:
  • name: 腳本名稱
  • namespace: 命名空間,腳本的網址或是作者的網址
  • version: 腳本的版本號碼
  • description: 描述,說明腳本功能
  • author: 作者
  • match: 要在哪些網址中執行
  • icon: 腳本的小圖示,使用 base64 編碼的圖片
  • grant: 標記需要的權限
下面是一個非常簡單的腳本,在開啟 Google map 網頁時會出現一個彈出視窗,顯示「腳本啟動!」,唯一最長的內容就是腳本 icon (小圖示)
    
// ==UserScript==
// @name         My first script
// @namespace    http://ruyut.com/
// @version      2023-12-15
// @description  這個是描述
// @author       Ruyut
// @match        https://www.google.com/maps/*
// @icon         data:image/png;base64,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
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    alert("腳本啟動!");
})();
    

icon 可以使用網路上的 png to base64 工具 取得 base64 字串,就可以貼上使用。

按下 Ctrl + S 儲存後可以到「已安裝的使用者腳本」中看到該腳本,目前已經在執行中

這時候開啟 Google Map 的網頁,連畫面還沒載入完就會出現提示訊息:

如果想要等畫面載入完成可以這樣做:
    
    window.addEventListener('load', function () {
        console.log('整個網頁載入完成');
    });
    

我們還可以動態將按鈕加入到畫面上,這裡使用一個計時器等待元素載入完成,然後再動態產生元素並插入:
    
const intervalId = setInterval(function () {
    const targetElement = document.querySelector('#gb > div > div > div.gb_Od.gb_Wf.gb_C');

    if (targetElement) {
        clearInterval(intervalId); // 停止計時器

        // 建立新按鈕
        const newButton = document.createElement('button');
        newButton.textContent = '新按鈕';

        // 加上圓角邊框
        newButton.style.borderRadius = '5px';
        newButton.style.border = '1px solid #d1d5db';

        // 加上按鈕事件
        newButton.addEventListener('click', function () {
            alert('按鈕被按下');
        });

        // 在第一個元素之前插入新按鈕
        targetElement.insertBefore(newButton, targetElement.firstChild);

    }
}, 200); // 每隔 0.2 秒檢查一次目標元素是否存在
    

話說「等待元素出現後再處理」這個功能很常會使用到,我們可以重構一下,方便復用:
    

/**
 * 等待目標元素存在後,執行傳入的匿名函式
 * @param selector
 * @param action
 * @param interval
 */
function doWhenElementExists(selector, action, interval = 200) {
    const intervalId = setInterval(function () {
        const targetElement = document.querySelector(selector);

        if (targetElement) {
            clearInterval(intervalId); // 停止計時器
            action(targetElement); // 執行傳入的匿名函式
        }
    }, interval);
}

doWhenElementExists(
    '#gb > div > div > div.gb_Od.gb_Wf.gb_C',
    (targetElement) => {
        // 建立新按鈕
        const newButton = document.createElement('button');
        newButton.textContent = '新按鈕';

        // 加上圓角邊框
        newButton.style.borderRadius = '5px';
        newButton.style.border = '1px solid #d1d5db';

        // 加上按鈕事件
        newButton.addEventListener('click', function () {
            alert('按鈕被按下');
        });

        // 在第一個元素之前插入新按鈕
        targetElement.insertBefore(newButton, targetElement.firstChild);
    }
);
    

Tampermonkey 除了可以修改/增加元素外,還可以攔截、呼叫 API 、儲存檔案等,有機會再繼續來示範

參考資料:
Tampermonkey

留言