您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds 'no access' or safety warnings to Google search results.
当前为
// ==UserScript== // @name Google Search Link Checker // @namespace http://tampermonkey.net/ // @version 1.1 // @description Adds 'no access' or safety warnings to Google search results. // @author Bui Quoc Dung // @match https://www.google.com/search* // @grant GM_xmlhttpRequest // @connect * // ==/UserScript== (function () { 'use strict'; async function checkLinkStatus(url) { return new Promise((resolve) => { GM_xmlhttpRequest({ method: "HEAD", url, timeout: 5000, onload: res => { const ok = (res.status >= 200 && res.status < 400) || res.status === 0 || res.status === 403 || res.status === 405; resolve(ok); }, onerror: () => resolve(false), ontimeout: () => resolve(false) }); }); } async function checkSafetyStatus(url) { try { const hostname = new URL(url).hostname; const apiUrl = `https://check.getsafeonline.org/check/${hostname}?inputUrl=${hostname}`; return new Promise((resolve) => { GM_xmlhttpRequest({ method: "GET", url: apiUrl, timeout: 10000, onload: res => { if (res.status >= 200 && res.status < 300) { const parser = new DOMParser(); const doc = parser.parseFromString(res.responseText, 'text/html'); const warningElement = doc.querySelector('div.font-light.text-2xl.mt-6 span.text-primary-red.font-bold'); if (warningElement) { resolve(warningElement.textContent.trim()); } else { resolve(null); } } else { resolve(null); } }, onerror: () => resolve(null), ontimeout: () => resolve(null) }); }); } catch (e) { console.error("Could not parse URL for safety check:", url, e); return Promise.resolve(null); } } function processLink(link) { if (!link || link.dataset.statusChecked) return; link.dataset.statusChecked = 'true'; const url = link.href; if (!url || url.startsWith('javascript:') || url.startsWith('#')) return; const h3 = link.querySelector('h3'); const targetElement = h3 || link; checkLinkStatus(url).then(accessible => { if (!accessible) { if (targetElement.querySelector('.no-access-tag')) return; const tag = document.createElement('span'); tag.textContent = '[no access]'; tag.className = 'no-access-tag'; tag.style.color = 'orange'; tag.style.fontSize = '0.8em'; tag.style.marginLeft = '4px'; targetElement.appendChild(tag); } }); checkSafetyStatus(url).then(safetyText => { if (safetyText) { if (targetElement.querySelector('.safety-warning-tag')) return; const tag = document.createElement('span'); tag.textContent = ` [${safetyText}]`; tag.className = 'safety-warning-tag'; tag.style.color = 'red'; tag.style.fontSize = '0.8em'; tag.style.marginLeft = '4px'; targetElement.appendChild(tag); } }); } let scanTimeoutId = null; function scanLinksDebounced() { clearTimeout(scanTimeoutId); scanTimeoutId = setTimeout(() => { document.querySelectorAll('div.g a:has(h3), div.MjjYud a:has(h3), div.hlcw0c a:has(h3), span.V9tjod a.zReHs').forEach(processLink); }, 300); } const observer = new MutationObserver(mutations => { for (const m of mutations) { for (const node of m.addedNodes) { if (node.nodeType === 1 && (node.querySelector('div.g a:has(h3), div.MjjYud a:has(h3), div.hlcw0c a:has(h3)') || node.matches('.g, .MjjYud, .hlcw0c'))) { scanLinksDebounced(); return; } } } }); const container = document.getElementById('center_col') || document.getElementById('rcnt') || document.body; observer.observe(container, { childList: true, subtree: true }); if (document.readyState === 'loading') { window.addEventListener('DOMContentLoaded', () => setTimeout(scanLinksDebounced, 1000)); } else { setTimeout(scanLinksDebounced, 1000); } })();