Greasy Fork

Greasy Fork is available in English.

屏蔽 CSDN

屏蔽 CSDN 及其它垃圾信息

目前为 2024-11-26 提交的版本。查看 最新版本

// ==UserScript==
// @name        屏蔽 CSDN
// @version    1.1.0
// @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. 添加Google搜索支持
//              2. 优化代码结构和性能
//              3. 改进屏蔽规则管理
//              4. 添加更详细的日志信息
// @namespace http://greasyfork.icu/users/1249199
// ==/UserScript==

// @notes: 优化代码, 新增 Bing 搜索过滤

    (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',
                        source: 'div[class*="source"]'
                    }
                },
                google: {
                    host: 'google.com',
                    container: '#search',
                    selectors: {
                        title: ['.VuuXrf'],
                        result: '.MjjYud'
                    }
                }
            },

            // 屏蔽规则配置
            blockRules: {
                // 技术网站
                tech: [
                    "CSDN博客", "CSDN技术社区", "csdn.net",
                    "简书", "博客园", "PHP中文网",
                    "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);
            }

            // 初始化观察器
            init() {
                if (!this.container) return;

                // 创建MutationObserver
                const observer = new MutationObserver(
                    utils.debounce(() => this.handler.removeBlockedSites(), 100)
                );

                // 配置观察器
                observer.observe(this.container, {
                    childList: true,
                    subtree: true
                });

                // 监听滚动事件
                window.addEventListener('scroll',
                    utils.debounce(() => this.handler.removeBlockedSites(), 100),
                    { passive: true }
                );

                // 初始执行
                this.handler.removeBlockedSites();
            }
        }

        // 初始化
        function init() {
            utils.log('info', '⚡ Content Blocker Activated! ⚡');
            const observer = new ResultObserver();
            observer.init();
        }

        // 启动脚本
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', init);
        } else {
            init();
        }
    })();