屏蔽 CSDN

屏蔽 CSDN 及其它垃圾信息

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        屏蔽 CSDN
// @version    1.1.3
// @author      aaron yan
// @description 屏蔽 CSDN 及其它垃圾信息
// @match       https://www.baidu.com
// @match       https://www.baidu.com/s*
// @match       https://www.google.com
// @match       https://www.google.com/search*
// @match       https://www.google.com.hk/search*
// @match       https://www.google.com.tw/search*
// @grant       GM_xmlhttpRequest

// @license     MIT

// @changelog    v1.1.0 (2024-01-17)
//              1. 优化代码结构和性能
//              2. 改进屏蔽规则管理
//              3. 去除延时响应
// @namespace https://greasyfork.org/users/1249199
// ==/UserScript==

(function () {
    // 配置对象
    const CONFIG = {
        // 搜索引擎配置
        engines: {
            baidu: {
                host: 'baidu.com',
                container: '#content_left',
                selectors: {
                    title: ['h3.c-title', '.t', '.tts-title', '.c-gap-right '],
                    url: '.c-showurl',
                    result: '.result.c-container, .c-container.new-pmd',
                    source: 'div[class*="source"]',
                    searchButton: '#su, input[type="submit"]'  // 百度搜索按钮
                }
            },
            google: {
                host: 'google.com',
                container: '#search',
                selectors: {
                    title: ['.VuuXrf'],
                    result: '.MjjYud',
                    searchButton: 'input[name="btnK"], input[type="submit"]'  // 谷歌搜索按钮
                }
            }
        },

        // 屏蔽规则配置
        blockRules: {
            // 技术网站
            tech: [
                "CSDN博客", "CSDN技术社区", "csdn.net",
                "简书", "PHP中文网",
                "Worktile", "慕课网", "知了爱学", "51CTO", "腾讯云计算",
                "360Doc", "千锋教育", "筋斗云"
            ],
            // 下载站点
            download: [
                "软件园", "下载之家", "下载网",
                "华军软件园", "当下软件园", "东坡下载站",
                "系统之家", "/soft/"
            ],
            // 医疗健康
            health: [
                "百度健康", "快速问医生", "求医网",
                "求医问药", "家庭医生", "寻医",
                "健康", "健客网", "医生"
            ],
            // 其他
            others: [
                "亿速云", "动力节点在线", "IT 技术博客",
                "千锋教育", "虎课网", "黑马程序员", "抖音"
            ]
        },

        // URL屏蔽规则
        blockUrls: [
            'douyin.com'
        ]
    };

    // 工具函数
    const utils = {
        // 防抖函数
        debounce(func, wait) {
            let timeout;
            return function executedFunction(...args) {
                const later = () => {
                    clearTimeout(timeout);
                    func(...args);
                };
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
            };
        },

        // 日志函数
        log(type, message, data = {}) {
            const styles = {
                block: 'color: #ff6b6b; font-weight: bold',
                info: 'color: #4CAF50; font-weight: bold',
                error: 'color: #f44336; font-weight: bold'
            };
            console.log(`%c ${message}`, styles[type]);
        },

        // 获取当前搜索引擎
        getCurrentEngine() {
            const host = window.location.hostname;
            return Object.entries(CONFIG.engines).find(([, config]) =>
                host.includes(config.host)
            )?.[0];
        },

        // 获取所有屏蔽关键词
        getAllBlockedSites() {
            return Object.values(CONFIG.blockRules)
                .flat()
                .filter((value, index, self) => self.indexOf(value) === index);
        }
    };

    // 搜索结果处理类
    class SearchResultHandler {
        constructor(engine) {
            this.engine = engine;
            this.config = CONFIG.engines[engine];
            this.blockedSites = utils.getAllBlockedSites();
        }

        // 检查是否应该屏蔽
        shouldBlock(element) {
            // 检查标题
            const titleSelectors = this.config.selectors.title;
            for (const selector of titleSelectors) {
                const titleElement = element.querySelector(selector);
                if (titleElement && this.blockedSites.some(site =>
                    titleElement.textContent.trim().includes(site))) {
                    return true;
                }
            }

            // 检查URL(如果有URL选择器)
            if (this.config.selectors.url) {
                const urlElement = element.querySelector(this.config.selectors.url);
                if (urlElement && CONFIG.blockUrls.some(url =>
                    urlElement.textContent.trim().includes(url))) {
                    return true;
                }
            }

            // 检查来源(如果有source选择器)
            if (this.config.selectors.source) {
                const sourceElement = element.querySelector(this.config.selectors.source);
                if (sourceElement && this.blockedSites.some(site =>
                    sourceElement.textContent.trim().includes(site))) {
                    return true;
                }
            }

            return false;
        }

        // 移除搜索结果
        removeBlockedSites() {
            try {
                const results = document.querySelectorAll(this.config.selectors.result);
                results.forEach(result => {
                    if (this.shouldBlock(result)) {
                        const title = result.querySelector(this.config.selectors.title[0])?.textContent.trim();
                        const source = result.querySelector(this.config.selectors.source)?.textContent.trim();
                        utils.log('block', 'Blocked:', {
                            title,
                            source: source || 'N/A'
                        });
                        result.remove();
                    }
                });
            } catch (error) {
                utils.log('error', `[${this.engine}] Error:`, error);
            }
        }
    }

    // 观察器类
    class ResultObserver {
        constructor() {
            this.engine = utils.getCurrentEngine();
            if (!this.engine) return;

            this.handler = new SearchResultHandler(this.engine);
            this.container = document.querySelector(CONFIG.engines[this.engine].container);
            this.observer = null;
        }

        init() {
            if (!this.container) return;

            this.observer = new MutationObserver(() => this.handler.removeBlockedSites());
            this.observer.observe(this.container, {
                childList: true,
                subtree: true
            });

            window.addEventListener('scroll',
                () => this.handler.removeBlockedSites(),
                { passive: true }
            );

            this.handler.removeBlockedSites();
        }

        reset() {
            if (this.observer) {
                this.observer.disconnect();
            }
            this.init();
        }
    }

    // 初始化
    function init() {
        utils.log('info', '⚡ Content Blocker Activated! ⚡');
        
        let observer = null;
        let lastUrl = location.href;

        function tryInit() {
            observer = new ResultObserver();
            if (observer.container) {
                observer.init();
            } else {
                setTimeout(tryInit, 100);
            }
        }

        tryInit();

        // 监听 URL 变化
        setInterval(() => {
            if (lastUrl !== location.href) {
                lastUrl = location.href;
                if (observer) {
                    observer.reset();
                } else {
                    tryInit();
                }
            }
        }, 1000);

        // 监听表单提交事件
        document.addEventListener('submit', (e) => {
            if (e.target.matches('form')) {
                setTimeout(() => {
                    if (observer) {
                        observer.reset();
                    } else {
                        tryInit();
                    }
                }, 500);
            }
        });

        // 监听回车键
        document.addEventListener('keypress', (e) => {
            if (e.key === 'Enter' && (e.target.matches('input[type="text"]') || e.target.matches('input[type="search"]'))) {
                setTimeout(() => {
                    if (observer) {
                        observer.reset();
                    } else {
                        tryInit();
                    }
                }, 500);
            }
        });
    }

    // 立即执行初始化
    init();
})();