❀ 浮岚 Bilibili 链接净化

加载前清洁链接,移除跟踪参数。

目前為 2025-11-04 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ❀ 浮岚 Bilibili 链接净化
// @namespace    https://bento.me/ranburiedbyacat
// @version      1.1.1
// @description  加载前清洁链接,移除跟踪参数。
// @author       嵐 @ranburiedbyacat
// @license      CC-BY-NC-SA-4.0
// @match        *://*.bilibili.com/*
// @compatible   Safari
// @compatible   Firefox
// @compatible   Chrome
// @icon         https://www.bilibili.com/favicon.ico
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    /**
     * ───────────────────────────────────────────────
     * ① 冗余参数
     * ───────────────────────────────────────────────
     */
    const chenruiMama = new Set([
        // ────────────── 来源跟踪 ────────────── 
        'spm_id_from', 'from_source', 'sourceFrom', 'from_spmid', 'csource', 'vd_source', 'source', 'search_source', 
        'from', 'buvid', 'mid', 'timestamp',
        // ────────────── 分享参数 ───────────────
        'share_source', 'share_medium', 'share_plat', 'share_session_id', 'share_tag', 'share_from', 'plat_id', 'up_id',
        // ────────────── 广告统计 ───────────────
        'trackid', 'session_id', 'visit_id', 'unique_k', 'spmid', '-Arouter',
        // ────────────── 功能标记 ───────────────
        'msource', 'bsource', 'tab', 'is_story_h5', 'hotRank', 'launch_id', 'live_from', 'popular_rank',
    ]);

    /**
     * ───────────────────────────────────────────────
     * ② URL 解析
     * ───────────────────────────────────────────────
     */
    function parseURL(str) {
        try {
            if (typeof str === 'string' && str.includes('.') && !/^[a-z]+:/.test(str)) {
                // 以 // 开头则补充协议
                str = str.startsWith("//") ? location.protocol + str : str;
            }
            return new URL(str, location.href);
        } catch (e) {
            return null;
        }
    }

    /**
     * ───────────────────────────────────────────────
     * ③ URL 净化
     * ───────────────────────────────────────────────
     */
    function cleanUrl(urlStr) {
        const url = parseURL(urlStr);
        if (!url) return urlStr;

        if (!/bilibili\.com/.test(url.hostname)) return urlStr;
        if (url.hostname.includes('bilibili.tv')) url.hostname = 'www.bilibili.com';

        // 删除冗余参数
        for (const key of Array.from(url.searchParams.keys())) {
            if (chenruiMama.has(key)) {
                url.searchParams.delete(key);
            }

            // 特殊处理 p 参数
            if (key === 'p') {
                const pVal = parseInt(url.searchParams.get('p'), 10);
                if (pVal === 1) {
                    url.searchParams.delete('p');
                }
            }
        }

        // 视频页面强制尾斜杠
        if (/^\/video\/BV/i.test(url.pathname) && !url.pathname.endsWith('/')) {
            url.pathname += '/';
        }

        // 视频页面 BV 号,且清洁后没有其他搜索参数时,强制尾斜杠
        if (/^\/video\/BV/i.test(url.pathname) && !url.pathname.endsWith('/') && !url.searchParams.toString()) {
        url.pathname += '/';
        }

        return url.toString();
    }

    /**
     * ───────────────────────────────────────────────
     * ④ 地址栏即时替换
     * ───────────────────────────────────────────────
     */
    function replaceLocation(url) {
        if (url !== location.href) {
            history.replaceState(history.state, '', url);
        }
    }

    replaceLocation(cleanUrl(location.href));

    /**
     * ───────────────────────────────────────────────
     * ⑤ 链接点击拦截
     * ───────────────────────────────────────────────
     */
    function handleClickCleanHistory(e) {
        const a = e.target.closest('a[href*="bilibili.com"]');
        if (!a) return;
        if (e.button !== 0) return;

        e.preventDefault();
        const clean = cleanUrl(a.href);

        if (a.target !== '_blank' && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
            history.replaceState(null, '', clean);
            location.assign(clean);
        } else {
            window.open(clean, '_blank');
        }
    }
    window.addEventListener('click', handleClickCleanHistory, true);

    /**
     * ───────────────────────────────────────────────
     * ⑥ window.open 拦截
     * ───────────────────────────────────────────────
     */
    const _open = window.open;
    window.open = (url, target, features) => _open.call(window, cleanUrl(url), target || '_blank', features);

    /**
     * ───────────────────────────────────────────────
     * ⑦ SPA 导航拦截
     * ───────────────────────────────────────────────
     */
    ['pushState', 'replaceState'].forEach(fn => {
        const orig = history[fn];
        history[fn] = (...args) => {
            if (typeof args[2] === 'string') {
                args[2] = cleanUrl(args[2]);
            }
            return orig.apply(history, args);
        };
    });

    /**
     * ───────────────────────────────────────────────
     * ⑧ Navigation API 拦截
     * ───────────────────────────────────────────────
     */
    if (window.navigation) {
        window.navigation.addEventListener('navigate', e => {
            const newURL = cleanUrl(e.destination.url);
            if (newURL !== e.destination.url) {
                e.preventDefault();
                if (newURL !== location.href) {
                    history.replaceState(history.state, '', newURL);
                }
            }
        });
    }

    /**
     * ───────────────────────────────────────────────
     * ⑨ 动态节点净化
     * ───────────────────────────────────────────────
     */
    const observer = new MutationObserver(muts => {
        for (const m of muts) {
            for (const node of m.addedNodes) {
                if (node.nodeType !== 1) continue;
                const links = node.querySelectorAll?.('a[href*="bilibili.com"]') || [];
                for (const a of links) {
                    a.href = cleanUrl(a.href);
                    a.removeAttribute('ping');
                }
            }
        }
    });
    observer.observe(document, { childList: true, subtree: true });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址