Greasy Fork

Greasy Fork is available in English.

Google搜索美化

美化Google搜索结果:宽屏居中显示、去除广告、背景色、悬停效果、整卡可点击、自动翻页、隐藏分页栏和推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @license MIT
// @name         Google搜索美化
// @namespace    豆沙包里加辣椒
// @version      8.1
// @description  美化Google搜索结果:宽屏居中显示、去除广告、背景色、悬停效果、整卡可点击、自动翻页、隐藏分页栏和推荐
// @author       User
// @match        https://www.google.com/search*
// @match        https://www.google.com.hk/search*
// @match        https://www.google.co.*/
// @match        https://*.google.*/
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    if (window.__gsBeautified) return;
    window.__gsBeautified = true;

    const CARD_BG = '#f5e4ea';
    const CARD_HOVER = '#e4f5f4';

    const CSS = `
        /* 隐藏广告 */
        #tads, #tadsb, #bottomads, .commercial_unit, .ads-ad,
        [data-text-ad], .uEierd, .U3A9Ac {
            display: none !important;
        }

        /* 隐藏底部分页栏 */
        #foot, #botstuff, .AaVjTc, #xjs, .T6zPgb, .mKDcx {
            display: none !important;
        }

        /* 隐藏搜索推荐/相关搜索 */
        #extrares, #bres, .iKt1P, .ZCeoTe, .A6I4wd, 
        .EIaa9b, .related-question-pair, .csAkad,
        #rso > div[data-hveid] > div[style*="margin"] {
            display: none !important;
        }

        /* 隐藏"人们也在问" */
        .related-question-pair, .iDjcJe {
            display: none !important;
        }

        /* 隐藏右侧栏 */
        #rhs, #rhscol {
            display: none !important;
        }

        /* 让 rcnt 撑满并居中 */
        #rcnt {
            width: 100% !important;
            max-width: 1100px !important;
            margin: 0 auto !important;
            box-sizing: border-box !important;
            display: block !important;
        }

        /* center_col 独占整行,不给右侧栏留空间 */
        #center_col {
            width: 100% !important;
            max-width: 100% !important;
            margin: 0 auto !important;
            box-sizing: border-box !important;
            grid-column: 1 / -1 !important;
        }

        /* 中间层容器撑满 */
        #rso, #search, #rso .dURPMd, #rso .eqAnXb, #rso .s6JM6d {
            width: 100% !important;
            box-sizing: border-box !important;
        }

        /* 搜索结果卡片 */
        #rso .MjjYud {
            background: ${CARD_BG} !important;
            border-radius: 10px !important;
            margin: 10px 0 !important;
            padding: 14px 18px !important;
            box-sizing: border-box !important;
            width: 100% !important;
            position: relative !important;
            overflow: hidden !important;
            cursor: pointer !important;
            transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease !important;
        }

        /* 悬停 */
        #rso .MjjYud:hover {
            background: ${CARD_HOVER} !important;
            transform: scale(1.012) !important;
            box-shadow: 0 4px 18px rgba(0,0,0,0.10) !important;
            z-index: 5 !important;
        }

        /* 扫光 */
        #rso .MjjYud::before {
            content: '' !important;
            position: absolute !important;
            top: 0 !important;
            left: -100% !important;
            width: 100% !important;
            height: 100% !important;
            background: linear-gradient(
                120deg,
                transparent 0%,
                rgba(0,255,255,0.15) 30%,
                rgba(138,43,226,0.12) 60%,
                transparent 100%
            ) !important;
            pointer-events: none !important;
            z-index: 1 !important;
            transition: left 1.2s ease !important;
        }

        #rso .MjjYud:hover::before {
            left: 100% !important;
        }

        /* 内容层级高于扫光 */
        #rso .MjjYud > * {
            position: relative !important;
            z-index: 2 !important;
        }

        /* 响应式 */
        @media (max-width: 768px) {
            #rcnt {
                padding: 0 10px !important;
            }
        }
    `;

    // ==================== 自动翻页功能 ====================
    
    // 翻页状态
    let isLoading = false;
    let loadedStarts = new Set();
    let currentStart = 0;

    // 获取URL参数
    function getUrlParam(name) {
        const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
        const r = window.location.search.substr(1).match(reg);
        return r ? decodeURIComponent(r[2]) : null;
    }

    // 显示提示
    function showToast(msg) {
        let toast = document.getElementById('__gs_toast__');
        if (!toast) {
            toast = document.createElement('div');
            toast.id = '__gs_toast__';
            toast.style.cssText = `
                position: fixed;
                bottom: 80px;
                left: 50%;
                transform: translateX(-50%);
                padding: 10px 20px;
                background: rgba(0, 0, 0, 0.7);
                color: white;
                border-radius: 8px;
                font-size: 14px;
                z-index: 99999;
                transition: opacity 0.3s ease;
            `;
            document.body.appendChild(toast);
        }
        
        toast.textContent = msg;
        toast.style.opacity = '1';
        
        setTimeout(() => {
            toast.style.opacity = '0';
        }, 1000);
    }

    // 加载下一页
    function loadNextPage() {
        if (isLoading) return;
        
        // 获取当前起始位置
        const startParam = getUrlParam('start');
        currentStart = startParam ? parseInt(startParam) : 0;
        
        const nextStart = currentStart + loadedStarts.size * 10;
        
        if (loadedStarts.has(nextStart)) return;
        loadedStarts.add(nextStart);
        
        isLoading = true;
        showToast(`加载第 ${Math.floor(nextStart / 10) + 1} 页...`);
        
        // 构造下一页URL
        const url = new URL(window.location.href);
        url.searchParams.set('start', nextStart);
        
        console.log('[Google美化] 加载下一页:', url.toString());
        
        fetch(url.toString())
            .then(response => response.text())
            .then(html => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                
                // 获取搜索结果卡片
                const results = doc.querySelectorAll('#rso .MjjYud');
                const container = document.querySelector('#rso');
                
                if (container && results.length > 0) {
                    let added = 0;
                    results.forEach(result => {
                        // 排除广告
                        if (!result.querySelector('.uEierd, .U3A9Ac, [data-text-ad]')) {
                            container.appendChild(result.cloneNode(true));
                            added++;
                        }
                    });
                    
                    if (added > 0) {
                        showToast(`已加载第 ${Math.floor(nextStart / 10) + 1} 页`);
                    } else {
                        showToast('没有更多结果了');
                    }
                } else {
                    showToast('没有更多结果了');
                }
                
                isLoading = false;
            })
            .catch(error => {
                console.error('[Google美化] 加载失败:', error);
                showToast('加载失败');
                isLoading = false;
                loadedStarts.delete(nextStart);
            });
    }

    // 回到顶部按钮
    let scrollToTopBtn = null;
    let isScrollVisible = false;

    function createScrollToTopButton() {
        if (scrollToTopBtn) return;
        
        scrollToTopBtn = document.createElement('div');
        scrollToTopBtn.id = '__gs_scroll_top__';
        scrollToTopBtn.innerHTML = `
            <svg viewBox="0 0 24 24" width="24" height="24" fill="#666">
                <path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path>
            </svg>
        `;
        scrollToTopBtn.style.cssText = `
            position: fixed;
            bottom: 80px;
            right: 50px;
            width: 44px;
            height: 44px;
            border-radius: 50%;
            background: #fff;
            box-shadow: 0 2px 8px rgba(0,0,0,0.15);
            cursor: pointer;
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 1000;
            transition: opacity 0.2s ease;
        `;
        scrollToTopBtn.onclick = () => {
            window.scrollTo({ top: 0, behavior: 'smooth' });
        };
        document.documentElement.appendChild(scrollToTopBtn);
    }

    function updateScrollToTop() {
        if (!scrollToTopBtn) return;
        
        const shouldShow = window.scrollY > 200;
        if (shouldShow !== isScrollVisible) {
            isScrollVisible = shouldShow;
            scrollToTopBtn.style.display = shouldShow ? 'flex' : 'none';
        }
    }

    // 滚动处理(防抖)
    let scrollTimer = null;
    function handleScroll() {
        updateScrollToTop();
        
        if (scrollTimer) clearTimeout(scrollTimer);
        
        scrollTimer = setTimeout(() => {
            const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
            const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
            
            const distanceToBottom = scrollHeight - scrollTop - clientHeight;
            
            if (distanceToBottom <= 100) {
                loadNextPage();
            }
        }, 150);
    }

    // ==================== 样式注入 ====================
    
    function injectStyle() {
        if (document.getElementById('__gs_beautify__')) return;
        const el = document.createElement('style');
        el.id = '__gs_beautify__';
        el.textContent = CSS;
        (document.head || document.documentElement).appendChild(el);
        console.log('[Google美化 v8.0] 样式注入成功');
    }

    // ==================== 卡片点击 ====================
    
    function bindClick() {
        if (window.__gsClickBound) return;
        window.__gsClickBound = true;

        document.addEventListener('click', function (e) {
            // 排除按钮、输入框等交互元素
            if (e.target.closest('button, input, select, textarea')) return;

            const card = e.target.closest('#rso .MjjYud');
            if (!card) return;

            // 查找卡片内的主链接
            const link = card.querySelector('.yuRUbf a') ||
                         card.querySelector('a[jsname] h3')?.closest('a') ||
                         card.querySelector('h3 a') ||
                         card.querySelector('a[href^="http"]');

            if (!link) return;

            const href = link.href;
            if (!href || href.includes('google.com/search')) return;

            // 无论点击卡片还是链接,都在新标签页打开
            e.preventDefault();
            e.stopPropagation();
            window.open(href, '_blank', 'noopener,noreferrer');
        }, true);
    }

    // ==================== 初始化 ====================
    
    function init() {
        injectStyle();
        bindClick();
        createScrollToTopButton();
        
        // 初始化已加载页码
        const startParam = getUrlParam('start');
        if (startParam) {
            loadedStarts.add(parseInt(startParam));
        }
    }

    // 样式注入
    if (document.head) {
        injectStyle();
    } else {
        const watcher = new MutationObserver(function () {
            if (document.head) {
                watcher.disconnect();
                injectStyle();
            }
        });
        watcher.observe(document.documentElement, { childList: true });
    }

    // DOM加载完成
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // URL变化监听
    let lastUrl = location.href;
    new MutationObserver(function () {
        if (location.href !== lastUrl) {
            lastUrl = location.href;
            loadedStarts.clear();
            const startParam = getUrlParam('start');
            if (startParam) {
                loadedStarts.add(parseInt(startParam));
            }
            setTimeout(init, 500);
        }
    }).observe(document.documentElement, { subtree: true, childList: true });

    window.addEventListener('popstate', () => {
        loadedStarts.clear();
        setTimeout(init, 500);
    });

    // 滚动监听
    window.addEventListener('scroll', handleScroll, { passive: true });

})();