- // ==UserScript==
- // @name 搜索引擎官网净化器-全自动版
- // @namespace http://tampermonkey.net/
- // @version 1.5
- // @description 全自动屏蔽虚假结果,无需手动操作(支持百度/谷歌/必应)
- // @author 高级优化版
- // @license MIT
- // @match *://www.baidu.com/*
- // @match *://www.google.com/*
- // @match *://www.bing.com/*
- // @grant GM_addStyle
- // @grant GM.getValue
- // @grant GM.setValue
- // @grant GM.registerMenuCommand
- // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
- // @noframes
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // 增强视觉样式(精简版)
- GM_addStyle(`
- .sg-official-mark {
- background: #2196F3 !important;
- border-radius: 3px;
- padding: 1px 5px;
- color: white !important;
- font-size: 0.75em;
- margin-left: 8px;
- vertical-align: middle;
- }
- .sg-dangerous-result {
- opacity: 0.25 !important;
- position: relative;
- transition: opacity 0.3s;
- }
- .sg-dangerous-result::before {
- content: "🚫 已屏蔽可疑结果";
- position: absolute;
- left: 0;
- right: 0;
- text-align: center;
- color: #d32f2f;
- font-weight: bold;
- z-index: 100;
- }
- `);
-
- // 持久化配置中心
- const SearchEngineConfig = {
- 'www.baidu.com': {
- selectors: {
- container: '#content_left',
- result: '.c-container, .result-op, [mu]',
- title: 'h3.t a', // 更精准的标题选择器
- url: 'a[href]'
- },
- official: {
- markers: [
- '.c-icon-certified', // 官方认证图标
- { type: 'text', pattern: /官网$/ }
- ],
- domains: [
- /\.(gov|edu)\.cn$/,
- /\.(com.cn|org.cn|net.cn)$/,
- /^(www\.)?(baidu|alibaba|tencent)\.com$/
- ]
- },
- danger: {
- markers: [
- '.c-tips-icon-warning', // 风险提示图标
- { type: 'text', pattern: /(彩票|刷单|网赚)/ }
- ],
- domains: [
- /\.(xyz|top|loan|tk|ml)$/,
- /(seo|wangzhan|daohang)/
- ]
- }
- },
- 'www.google.com': {
- selectors: {
- container: '#search',
- result: '.g:not(.ULSxyf)',
- title: 'h3',
- url: 'a[href]'
- },
- official: {
- markers: [
- '[aria-label="Verified"]', // 认证标记
- { type: 'text', pattern: / - Official Site$/i }
- ],
- domains: [
- /\.(gov|edu|mil)$/,
- /^(www\.)?(google|microsoft|apple)\.com$/
- ]
- },
- danger: {
- markers: [
- '[aria-label="Warning"]', // 危险提示
- { type: 'text', pattern: /(casino|porn|pharmacy)/i }
- ],
- domains: [
- /\.(bid|loan|top)$/,
- /(freevpn|cheapdrugs)/
- ]
- }
- },
- 'www.bing.com': {
- selectors: {
- container: '#b_results',
- result: '.b_algo',
- title: 'h2 a',
- url: 'a[href]'
- },
- official: {
- markers: [
- '[aria-label="官方站点"]',
- { type: 'text', pattern: /Official Site/i }
- ],
- domains: [
- /\.(gov|edu)/,
- /^(www\.)?(microsoft|bing)\.com$/
- ]
- },
- danger: {
- markers: [
- '.b_mhdr', // 必应危险标识
- { type: 'text', pattern: /(赌博|诈骗)/i }
- ],
- domains: [
- /\.(stream|gq|cf)/,
- /(poker|bitcoin)/
- ]
- }
- }
- };
-
- class SearchGuardPro {
- constructor() {
- this.engine = location.hostname;
- this.config = SearchEngineConfig[this.engine];
- if (!this.config) return;
-
- this.init().catch(console.error);
- }
-
- async init() {
- this.enabled = await GM.getValue('sgEnabled', true);
- this.setupAutoRefresh();
- this.processAllResults();
- this.setupPersistentObserver();
- }
-
- setupAutoRefresh() {
- // 自动处理新加载结果
- const observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
- mutation.addedNodes.forEach(node => {
- if (node.nodeType === 1 && node.matches(this.config.selectors.result)) {
- this.processResult(node);
- }
- });
- });
- });
-
- const container = document.querySelector(this.config.selectors.container);
- if (container) {
- observer.observe(container, {
- childList: true,
- subtree: true
- });
- }
-
- // 应对无限滚动
- setInterval(() => this.processAllResults(), 1500);
- }
-
- setupPersistentObserver() {
- // 页面完全加载后重新检查
- window.addEventListener('load', () => this.processAllResults());
- // 历史记录导航时检查
- window.addEventListener('popstate', () => this.processAllResults());
- }
-
- processAllResults() {
- if (!this.enabled) return;
- document.querySelectorAll(this.config.selectors.result).forEach(el => {
- if (!el.dataset.sgProcessed) this.processResult(el);
- });
- }
-
- processResult(element) {
- element.dataset.sgProcessed = true;
- const url = this.getResultUrl(element);
- if (!url) return;
-
- if (this.isDangerous(element, url)) {
- this.markAsDangerous(element);
- } else if (this.isOfficial(element, url)) {
- this.markAsOfficial(element);
- }
- }
-
- getResultUrl(element) {
- const link = element.querySelector(this.config.selectors.url);
- try {
- return new URL(link.href).hostname;
- } catch {
- return null;
- }
- }
-
- isOfficial(element, url) {
- return this.config.official.markers.some(marker => {
- if (typeof marker === 'string') return element.querySelector(marker);
- if (marker.type === 'text') return marker.pattern.test(element.textContent);
- return false;
- }) || this.config.official.domains.some(domain => domain.test(url));
- }
-
- isDangerous(element, url) {
- return this.config.danger.markers.some(marker => {
- if (typeof marker === 'string') return element.querySelector(marker);
- if (marker.type === 'text') return marker.pattern.test(element.textContent);
- return false;
- }) || this.config.danger.domains.some(domain => domain.test(url));
- }
-
- markAsOfficial(element) {
- const title = element.querySelector(this.config.selectors.title);
- if (!title || title.querySelector('.sg-official-mark')) return;
-
- const mark = document.createElement('span');
- mark.className = 'sg-official-mark';
- mark.textContent = this.getOfficialText();
- title.appendChild(mark);
- }
-
- getOfficialText() {
- return {
- 'www.baidu.com': '官',
- 'www.google.com': '✓',
- 'www.bing.com': '✔'
- }[this.engine];
- }
-
- markAsDangerous(element) {
- element.classList.add('sg-dangerous-result');
- element.querySelector('a')?.addEventListener('click', e => {
- e.stopPropagation();
- e.preventDefault();
- this.showWarningToast();
- });
- }
-
- showWarningToast() {
- const toast = document.createElement('div');
- toast.textContent = '⚠️ 已拦截危险网站访问';
- toast.style = `position:fixed;bottom:20px;left:50%;transform:translateX(-50%);
- background:#d32f2f;color:white;padding:12px 24px;border-radius:25px;
- box-shadow:0 4px 12px rgba(0,0,0,0.15);z-index:9999;`;
- document.body.appendChild(toast);
- setTimeout(() => toast.remove(), 3000);
- }
- }
-
- // 自启动且带错误恢复
- let retryCount = 0;
- function init() {
- try {
- new SearchGuardPro();
- } catch (error) {
- if (retryCount++ < 3) {
- setTimeout(init, 1000 * retryCount);
- }
- console.error('[SearchGuard] 初始化错误:', error);
- }
- }
-
- // 页面加载完成后启动
- if (document.readyState === 'complete') {
- init();
- } else {
- window.addEventListener('load', init);
- document.addEventListener('DOMContentLoaded', init);
- }
- })();