搜索引擎官网净化器-全自动版

全自动屏蔽虚假结果,无需手动操作(支持百度/谷歌/必应)

  1. // ==UserScript==
  2. // @name 搜索引擎官网净化器-全自动版
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.5
  5. // @description 全自动屏蔽虚假结果,无需手动操作(支持百度/谷歌/必应)
  6. // @author 高级优化版
  7. // @license MIT
  8. // @match *://www.baidu.com/*
  9. // @match *://www.google.com/*
  10. // @match *://www.bing.com/*
  11. // @grant GM_addStyle
  12. // @grant GM.getValue
  13. // @grant GM.setValue
  14. // @grant GM.registerMenuCommand
  15. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
  16. // @noframes
  17. // ==/UserScript==
  18.  
  19. (function() {
  20. 'use strict';
  21.  
  22. // 增强视觉样式(精简版)
  23. GM_addStyle(`
  24. .sg-official-mark {
  25. background: #2196F3 !important;
  26. border-radius: 3px;
  27. padding: 1px 5px;
  28. color: white !important;
  29. font-size: 0.75em;
  30. margin-left: 8px;
  31. vertical-align: middle;
  32. }
  33. .sg-dangerous-result {
  34. opacity: 0.25 !important;
  35. position: relative;
  36. transition: opacity 0.3s;
  37. }
  38. .sg-dangerous-result::before {
  39. content: "🚫 已屏蔽可疑结果";
  40. position: absolute;
  41. left: 0;
  42. right: 0;
  43. text-align: center;
  44. color: #d32f2f;
  45. font-weight: bold;
  46. z-index: 100;
  47. }
  48. `);
  49.  
  50. // 持久化配置中心
  51. const SearchEngineConfig = {
  52. 'www.baidu.com': {
  53. selectors: {
  54. container: '#content_left',
  55. result: '.c-container, .result-op, [mu]',
  56. title: 'h3.t a', // 更精准的标题选择器
  57. url: 'a[href]'
  58. },
  59. official: {
  60. markers: [
  61. '.c-icon-certified', // 官方认证图标
  62. { type: 'text', pattern: /官网$/ }
  63. ],
  64. domains: [
  65. /\.(gov|edu)\.cn$/,
  66. /\.(com.cn|org.cn|net.cn)$/,
  67. /^(www\.)?(baidu|alibaba|tencent)\.com$/
  68. ]
  69. },
  70. danger: {
  71. markers: [
  72. '.c-tips-icon-warning', // 风险提示图标
  73. { type: 'text', pattern: /(彩票|刷单|网赚)/ }
  74. ],
  75. domains: [
  76. /\.(xyz|top|loan|tk|ml)$/,
  77. /(seo|wangzhan|daohang)/
  78. ]
  79. }
  80. },
  81. 'www.google.com': {
  82. selectors: {
  83. container: '#search',
  84. result: '.g:not(.ULSxyf)',
  85. title: 'h3',
  86. url: 'a[href]'
  87. },
  88. official: {
  89. markers: [
  90. '[aria-label="Verified"]', // 认证标记
  91. { type: 'text', pattern: / - Official Site$/i }
  92. ],
  93. domains: [
  94. /\.(gov|edu|mil)$/,
  95. /^(www\.)?(google|microsoft|apple)\.com$/
  96. ]
  97. },
  98. danger: {
  99. markers: [
  100. '[aria-label="Warning"]', // 危险提示
  101. { type: 'text', pattern: /(casino|porn|pharmacy)/i }
  102. ],
  103. domains: [
  104. /\.(bid|loan|top)$/,
  105. /(freevpn|cheapdrugs)/
  106. ]
  107. }
  108. },
  109. 'www.bing.com': {
  110. selectors: {
  111. container: '#b_results',
  112. result: '.b_algo',
  113. title: 'h2 a',
  114. url: 'a[href]'
  115. },
  116. official: {
  117. markers: [
  118. '[aria-label="官方站点"]',
  119. { type: 'text', pattern: /Official Site/i }
  120. ],
  121. domains: [
  122. /\.(gov|edu)/,
  123. /^(www\.)?(microsoft|bing)\.com$/
  124. ]
  125. },
  126. danger: {
  127. markers: [
  128. '.b_mhdr', // 必应危险标识
  129. { type: 'text', pattern: /(赌博|诈骗)/i }
  130. ],
  131. domains: [
  132. /\.(stream|gq|cf)/,
  133. /(poker|bitcoin)/
  134. ]
  135. }
  136. }
  137. };
  138.  
  139. class SearchGuardPro {
  140. constructor() {
  141. this.engine = location.hostname;
  142. this.config = SearchEngineConfig[this.engine];
  143. if (!this.config) return;
  144.  
  145. this.init().catch(console.error);
  146. }
  147.  
  148. async init() {
  149. this.enabled = await GM.getValue('sgEnabled', true);
  150. this.setupAutoRefresh();
  151. this.processAllResults();
  152. this.setupPersistentObserver();
  153. }
  154.  
  155. setupAutoRefresh() {
  156. // 自动处理新加载结果
  157. const observer = new MutationObserver(mutations => {
  158. mutations.forEach(mutation => {
  159. mutation.addedNodes.forEach(node => {
  160. if (node.nodeType === 1 && node.matches(this.config.selectors.result)) {
  161. this.processResult(node);
  162. }
  163. });
  164. });
  165. });
  166.  
  167. const container = document.querySelector(this.config.selectors.container);
  168. if (container) {
  169. observer.observe(container, {
  170. childList: true,
  171. subtree: true
  172. });
  173. }
  174.  
  175. // 应对无限滚动
  176. setInterval(() => this.processAllResults(), 1500);
  177. }
  178.  
  179. setupPersistentObserver() {
  180. // 页面完全加载后重新检查
  181. window.addEventListener('load', () => this.processAllResults());
  182. // 历史记录导航时检查
  183. window.addEventListener('popstate', () => this.processAllResults());
  184. }
  185.  
  186. processAllResults() {
  187. if (!this.enabled) return;
  188. document.querySelectorAll(this.config.selectors.result).forEach(el => {
  189. if (!el.dataset.sgProcessed) this.processResult(el);
  190. });
  191. }
  192.  
  193. processResult(element) {
  194. element.dataset.sgProcessed = true;
  195. const url = this.getResultUrl(element);
  196. if (!url) return;
  197.  
  198. if (this.isDangerous(element, url)) {
  199. this.markAsDangerous(element);
  200. } else if (this.isOfficial(element, url)) {
  201. this.markAsOfficial(element);
  202. }
  203. }
  204.  
  205. getResultUrl(element) {
  206. const link = element.querySelector(this.config.selectors.url);
  207. try {
  208. return new URL(link.href).hostname;
  209. } catch {
  210. return null;
  211. }
  212. }
  213.  
  214. isOfficial(element, url) {
  215. return this.config.official.markers.some(marker => {
  216. if (typeof marker === 'string') return element.querySelector(marker);
  217. if (marker.type === 'text') return marker.pattern.test(element.textContent);
  218. return false;
  219. }) || this.config.official.domains.some(domain => domain.test(url));
  220. }
  221.  
  222. isDangerous(element, url) {
  223. return this.config.danger.markers.some(marker => {
  224. if (typeof marker === 'string') return element.querySelector(marker);
  225. if (marker.type === 'text') return marker.pattern.test(element.textContent);
  226. return false;
  227. }) || this.config.danger.domains.some(domain => domain.test(url));
  228. }
  229.  
  230. markAsOfficial(element) {
  231. const title = element.querySelector(this.config.selectors.title);
  232. if (!title || title.querySelector('.sg-official-mark')) return;
  233.  
  234. const mark = document.createElement('span');
  235. mark.className = 'sg-official-mark';
  236. mark.textContent = this.getOfficialText();
  237. title.appendChild(mark);
  238. }
  239.  
  240. getOfficialText() {
  241. return {
  242. 'www.baidu.com': '官',
  243. 'www.google.com': '✓',
  244. 'www.bing.com': '✔'
  245. }[this.engine];
  246. }
  247.  
  248. markAsDangerous(element) {
  249. element.classList.add('sg-dangerous-result');
  250. element.querySelector('a')?.addEventListener('click', e => {
  251. e.stopPropagation();
  252. e.preventDefault();
  253. this.showWarningToast();
  254. });
  255. }
  256.  
  257. showWarningToast() {
  258. const toast = document.createElement('div');
  259. toast.textContent = '⚠️ 已拦截危险网站访问';
  260. toast.style = `position:fixed;bottom:20px;left:50%;transform:translateX(-50%);
  261. background:#d32f2f;color:white;padding:12px 24px;border-radius:25px;
  262. box-shadow:0 4px 12px rgba(0,0,0,0.15);z-index:9999;`;
  263. document.body.appendChild(toast);
  264. setTimeout(() => toast.remove(), 3000);
  265. }
  266. }
  267.  
  268. // 自启动且带错误恢复
  269. let retryCount = 0;
  270. function init() {
  271. try {
  272. new SearchGuardPro();
  273. } catch (error) {
  274. if (retryCount++ < 3) {
  275. setTimeout(init, 1000 * retryCount);
  276. }
  277. console.error('[SearchGuard] 初始化错误:', error);
  278. }
  279. }
  280.  
  281. // 页面加载完成后启动
  282. if (document.readyState === 'complete') {
  283. init();
  284. } else {
  285. window.addEventListener('load', init);
  286. document.addEventListener('DOMContentLoaded', init);
  287. }
  288. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址