AD block(Weiren)

拋棄雜七雜八的廣吿攔截器,試試這款輕量級 屏蔽廣告、彈窗、追蹤器

  1. // ==UserScript==
  2. // @name AD block(Weiren)
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.0
  5. // @description 拋棄雜七雜八的廣吿攔截器,試試這款輕量級 屏蔽廣告、彈窗、追蹤器
  6. // @author Weiren
  7. // @match *://*/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. // Google Ads 域名列表(包括子網)
  15. const googleAdsDomains = [
  16. '*://*.googleads.g.doubleclick.net/*',
  17. '*://*.pagead2.googlesyndication.com/*',
  18. '*://*.adservice.google.com/*',
  19. '*://*.gstatic.com/ads/*',
  20. '*://*.googletagservices.com/*',
  21. '*://*.googlesyndication.com/*'
  22. ];
  23.  
  24. // cat.sg1 廣告域名
  25. const catSg1AdsDomains = [
  26. '*://cat.sg1/*', // 假設這是 cat.sg1 的廣告域名,根據實際情況調整
  27. '*://*.cat.sg1/*' // 子網也加入
  28. ];
  29.  
  30. // 通用廣告及追蹤器域名
  31. const adAndTrackerDomains = [
  32. '*://*.doubleclick.net/*',
  33. '*://*.adnxs.com/*',
  34. '*://*.adsafeprotected.com/*',
  35. '*://*.adform.net/*',
  36. '*://*.taboola.com/*',
  37. '*://*.outbrain.com/*',
  38. '*://*.criteo.com/*'
  39. ];
  40.  
  41. // Google Forms 廣告元素識別
  42. const formsAdSelectors = [
  43. 'iframe[src*="doubleclick.net"]',
  44. 'iframe[src*="googlesyndication.com"]',
  45. '.adsbygoogle', // 常見的 Google Ads 類
  46. '.google-ads-frame' // 另一種常見的 Google Forms 廣告標識
  47. ];
  48.  
  49. // cat.sg1 廣告元素識別(假設的元素名稱,根據實際情況調整)
  50. const catSg1AdSelectors = [
  51. 'iframe[src*="cat.sg1"]', // 針對 cat.sg1 網站中的 iframe 廣告
  52. '.cat-ad', // 假設的廣告 class 名稱,根據實際情況調整
  53. '[id*="cat-ad"]', // 假設的廣告 ID 名稱
  54. '.cat-popup', // 假設的彈窗 class 名稱
  55. '[data-ad*="cat.sg1"]' // 假設的屬性選擇器
  56. ];
  57.  
  58. const allBlockedDomains = [...googleAdsDomains, ...catSg1AdsDomains, ...adAndTrackerDomains];
  59. const domainRegex = new RegExp(allBlockedDomains.map(domain => domain.replace(/\*/g, '.*')).join('|'), 'i');
  60.  
  61. let adRegexList = [];
  62. let trackerRegexList = [];
  63.  
  64. // 載入規則文件
  65. function loadRules(url, targetList) {
  66. GM_xmlhttpRequest({
  67. method: 'GET',
  68. url: url,
  69. onload: function (response) {
  70. const rules = response.responseText.split('\n');
  71. const regexList = rules
  72. .filter(rule => rule.startsWith('||') && rule.includes('^'))
  73. .map(rule => new RegExp(rule.replace('||', '').replace('^', '').trim()));
  74. targetList.push(...regexList);
  75. console.log(`規則已載入:${url},共解析到 ${regexList.length} 條規則`);
  76. },
  77. onerror: function () {
  78. console.error(`無法載入規則:${url}`);
  79. },
  80. });
  81. }
  82.  
  83. // 攔截 XMLHttpRequest
  84. const originalOpen = XMLHttpRequest.prototype.open;
  85. XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
  86. if (domainRegex.test(url) || adRegexList.some(regex => regex.test(url)) || trackerRegexList.some(regex => regex.test(url))) {
  87. console.log(`攔截請求: ${url}`);
  88. return; // 阻止請求
  89. }
  90. return originalOpen.apply(this, arguments);
  91. };
  92.  
  93. // 攔截 Fetch API
  94. const originalFetch = window.fetch;
  95. window.fetch = function (url, options) {
  96. if (domainRegex.test(url.toString()) || adRegexList.some(regex => regex.test(url.toString())) || trackerRegexList.some(regex => regex.test(url.toString()))) {
  97. console.log(`攔截 Fetch API 請求: ${url}`);
  98. return Promise.reject('攔截的廣告或追蹤請求');
  99. }
  100. return originalFetch.apply(this, arguments);
  101. };
  102.  
  103. // 隱藏廣告、追蹤器和彈窗元素
  104. GM_addStyle(`
  105. iframe, .ad, .ads, .sponsored, .advertisement,
  106. [id*="ad"], [class*="ad"], [data-ad], [aria-label*="advertisement"],
  107. [id*="popup"], [class*="popup"], [data-popup], .modal, .overlay,
  108. ${formsAdSelectors.join(', ')},
  109. ${catSg1AdSelectors.join(', ')} {
  110. display: none !important;
  111. }
  112. `);
  113.  
  114. // 使用 MutationObserver 隱藏動態生成的彈窗和廣告元素
  115. const observer = new MutationObserver(mutations => {
  116. mutations.forEach(mutation => {
  117. mutation.addedNodes.forEach(node => {
  118. if (node.nodeType === 1) { // 元素節點
  119. const nodeHtml = node.outerHTML || '';
  120. if (
  121. node.matches('[id*="popup"], [class*="popup"], .modal, .overlay') ||
  122. domainRegex.test(nodeHtml) ||
  123. formsAdSelectors.some(selector => node.matches(selector)) ||
  124. catSg1AdSelectors.some(selector => node.matches(selector))
  125. ) {
  126. console.log('動態攔截並移除元素:', node);
  127. node.remove();
  128. }
  129. }
  130. });
  131. });
  132. });
  133. observer.observe(document.body, { childList: true, subtree: true });
  134.  
  135. // 阻止常見的彈窗事件
  136. window.addEventListener('load', () => {
  137. document.querySelectorAll('[onclick*="popup"], [onmouseover*="popup"]').forEach(el => el.removeAttribute('onclick'));
  138. });
  139. window.addEventListener('beforeunload', e => e.preventDefault());
  140. window.addEventListener('popstate', e => e.preventDefault());
  141.  
  142. // 加載廣告過濾規則
  143. loadRules('https://easylist.to/easylist/easylist.txt', adRegexList); // EasyList 廣告規則
  144. loadRules('https://easylist.to/easylist/easyprivacy.txt', trackerRegexList); // EasyPrivacy 追蹤器規則
  145. loadRules('https://filters.adtidy.org/extension/chromium/filters/2.txt', adRegexList); // AdGuard Base filter
  146. loadRules('https://filters.adtidy.org/extension/chromium/filters/3.txt', trackerRegexList); // AdGuard Tracking Protection
  147.  
  148. console.log('最強廣告攔截腳本已啟動');
  149. })();