Greasy Fork

来自缓存

Greasy Fork is available in English.

FUCK CSDN(去除csdn搜索结果—百度/Google/Bing)

搜索时自动注入 -site:csdn.net 过滤CSDN

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         FUCK CSDN(去除csdn搜索结果—百度/Google/Bing)
// @version      1.6
// @namespace    http://greasyfork.icu/users/timmy
// @license      MIT
// @icon         https://free.picui.cn/free/2026/04/27/69eefef831bfd.png
// @description  搜索时自动注入 -site:csdn.net 过滤CSDN
// @author       timmy
// @match        *://www.google.com/*
// @match        *://www.google.com.hk/*
// @match        *://www.google.co.jp/*
// @match        *://www.baidu.com/*
// @match        *://www.bing.com/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  const BLOCKED = ['csdn.net'];
  const EXCLUDE_SUFFIX = BLOCKED.map(d => `-site:${d}`).join(' ');

  function getEngine() {
    const h = location.hostname;
    if (h.includes('baidu.com'))  return 'baidu';
    if (h.includes('google.'))    return 'google';
    if (h.includes('bing.com'))   return 'bing';
    return null;
  }

  function getInputSelector(engine) {
    if (engine === 'baidu')  return '#kw';
    if (engine === 'google') return 'input[name="q"]';
    if (engine === 'bing')   return '#sb_form_q';
    return null;
  }

  function getParamName(engine) {
    if (engine === 'baidu') return 'wd';
    return 'q';
  }

  function stripExclude(val) {
    if (!val) return '';
    return BLOCKED.reduce((acc, d) => {
      return acc.replace(new RegExp(`\\s*-site:${d.replace('.', '\\.')}`, 'gi'), '');
    }, val).trimEnd();
  }

  function injectExclude(val) {
    const base = stripExclude(val).trimEnd();
    if (!base) return base;
    return base + ' ' + EXCLUDE_SUFFIX;
  }

  // 注入 URL 字符串里的搜索参数
  function injectUrl(url) {
    try {
      const urlObj = new URL(url, location.origin);
      // 只处理百度搜索路径
      if (!urlObj.pathname.startsWith('/s') && urlObj.pathname !== '/') return url;
      const params = ['wd', 'word', 'kw'];
      let changed = false;
      for (const p of params) {
        const val = urlObj.searchParams.get(p);
        if (val) {
          const injected = injectExclude(val);
          if (injected !== val) {
            urlObj.searchParams.set(p, injected);
            changed = true;
          }
        }
      }
      return changed ? urlObj.toString() : url;
    } catch (e) {
      return url;
    }
  }

  // 拦截百度的 XHR 请求
  function interceptXHR() {
    const OrigOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function (method, url, ...rest) {
      const newUrl = injectUrl(url);
      return OrigOpen.call(this, method, newUrl, ...rest);
    };
  }

  // 拦截百度的 fetch 请求
  function interceptFetch() {
    const origFetch = window.fetch;
    window.fetch = function (input, init) {
      if (typeof input === 'string') {
        input = injectUrl(input);
      } else if (input instanceof Request) {
        const newUrl = injectUrl(input.url);
        if (newUrl !== input.url) {
          input = new Request(newUrl, input);
        }
      }
      return origFetch.call(this, input, init);
    };
  }

  // 拦截 history.pushState / replaceState(百度结果页跳转用这个)
  function interceptHistory() {
    ['pushState', 'replaceState'].forEach(method => {
      const orig = history[method];
      history[method] = function (state, title, url) {
        if (url) {
          url = injectUrl(url);
        }
        return orig.call(this, state, title, url);
      };
    });
  }

  function checkUrlOnLoad(engine) {
    const isResultPage =
      (engine === 'baidu'  && /\/s\b/.test(location.pathname)) ||
      (engine === 'google' && location.pathname === '/search')  ||
      (engine === 'bing'   && location.pathname === '/search');

    if (!isResultPage) return;

    const sp = new URLSearchParams(location.search);
    const param = getParamName(engine);
    const raw = sp.get(param) || sp.get('word') || sp.get('kw');
    if (!raw) return;

    const injected = injectExclude(raw);
    if (injected === raw) return;

    sp.set(param, injected);
    location.replace(`${location.pathname}?${sp}`);
  }

  function waitForElement(selector, cb, timeout = 8000) {
    const el = document.querySelector(selector);
    if (el) { cb(el); return; }
    const obs = new MutationObserver((_, o) => {
      const found = document.querySelector(selector);
      if (found) { o.disconnect(); cb(found); }
    });
    obs.observe(document.documentElement, { childList: true, subtree: true });
    setTimeout(() => obs.disconnect(), timeout);
  }

  function setupInputHandler(inputEl) {
    if (inputEl.dataset.filterEnabled) return;
    inputEl.dataset.filterEnabled = '1';

    let userVal = stripExclude(inputEl.value);

    inputEl.addEventListener('focus', () => {
      inputEl.value = userVal;
    });
    inputEl.addEventListener('input', () => {
      userVal = stripExclude(inputEl.value);
    });
    inputEl.addEventListener('blur', () => {
      userVal = stripExclude(inputEl.value);
      if (userVal) inputEl.value = injectExclude(userVal);
    });
    inputEl.addEventListener('keydown', (e) => {
      if (e.key !== 'Enter') return;
      userVal = stripExclude(inputEl.value);
      inputEl.value = injectExclude(userVal);
    });

    const form = inputEl.closest('form');
    if (form) {
      form.addEventListener('submit', () => {
        userVal = stripExclude(inputEl.value);
        inputEl.value = injectExclude(userVal);
      }, { capture: true });
    }

    ['#su', '#search-form .btn', 'input[type=submit]', 'button[type=submit]'].forEach(sel => {
      document.querySelectorAll(sel).forEach(btn => {
        btn.addEventListener('click', () => {
          userVal = stripExclude(inputEl.value);
          inputEl.value = injectExclude(userVal);
        }, { capture: true });
      });
    });
  }

  function watchInputRebind(selector) {
    let lastEl = null;
    const obs = new MutationObserver(() => {
      const el = document.querySelector(selector);
      if (el && el !== lastEl) {
        lastEl = el;
        setupInputHandler(el);
      }
    });
    obs.observe(document.documentElement, { childList: true, subtree: true });
  }

  const engine = getEngine();
  if (!engine) return;

  // 百度专项:document-start 阶段拦截所有网络请求和历史跳转
  if (engine === 'baidu') {
    interceptXHR();
    interceptFetch();
    interceptHistory();
  }

  checkUrlOnLoad(engine);

  const selector = getInputSelector(engine);
  if (!selector) return;

  function initDom() {
    waitForElement(selector, setupInputHandler);
    if (engine === 'baidu') {
      watchInputRebind(selector);
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initDom);
  } else {
    initDom();
  }

})();