jx filter ad

jx filter ad,不保证适用所有的jx页面,自用~

  1. // ==UserScript==
  2. // @name jx filter ad
  3. // @namespace http://tampermonkey.net/
  4. // @version 3.0.0
  5. // @description jx filter ad,不保证适用所有的jx页面,自用~
  6. // @author ltxlong
  7. // @match *://*/*
  8. // @grant none
  9. // @license MIT
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let jx_filter_ad_open_flag = false;
  17. const the_jx_url_trait = [
  18. 'v.qq.com',
  19. 'iqiyi.com',
  20. 'iq.com',
  21. 'youku.com',
  22. 'le.com',
  23. 'tudou.com',
  24. 'mgtv.com',
  25. 'sohu.com',
  26. '1905.com',
  27. 'bilibili.com',
  28. 'pptv.com',
  29. 'baofeng.com',
  30. 'acfun.cn',
  31. 'miguvideo.com',
  32. 'yinyuetai.com',
  33. 'fun.tv',
  34. 'wasu.cn'
  35. ];
  36.  
  37. const originUrl = window.location.origin;
  38. const originSearch = window.location.search;
  39.  
  40. const hasMatchInSearch = the_jx_url_trait.some(trait => originSearch.includes(trait));
  41. if (hasMatchInSearch) {
  42. jx_filter_ad_open_flag = true;
  43. }
  44.  
  45. if (!jx_filter_ad_open_flag) {
  46. return;
  47. }
  48.  
  49. // 可以自定义需要去掉的id和class和其他定义的元素
  50. const adEleId = [];
  51. const adEleClass = [];
  52. const adEleOther = ['span[id]'];
  53.  
  54. // 固定为PC ua
  55. Object.defineProperty(navigator, 'userAgent', {
  56. get: function () {
  57. return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36';
  58. }
  59. });
  60.  
  61. // Hook setInterval
  62. try {
  63. const originalSetInterval = window.setInterval;
  64. window.setInterval = function(callback, delay, ...args) {
  65.  
  66. const callbackString = callback.toString();
  67. const filterPatterns = [
  68. '.appendChild(',
  69. '.insertBefore(',
  70. '.insertAfter(',
  71. '.append(',
  72. '.prepend(',
  73. '.after(',
  74. '.before(',
  75. '.appendTo(',
  76. '.prependTo(',
  77. '.html(',
  78. '.replaceWith(',
  79. '.wrap(',
  80. '.wrapAll(',
  81. '.wrapInner(',
  82. ];
  83.  
  84. let isBlockFlag = false;
  85. if (typeof callbackString === 'string' && callbackString !== '[native code]') {
  86. for (const pattern of filterPatterns) {
  87. if (callbackString.includes(pattern)) {
  88. console.warn(`HOOK: Callback string contains filter pattern: "${pattern}"`);
  89. isBlockFlag = true;
  90. break;
  91. }
  92. }
  93. }
  94.  
  95. if (isBlockFlag) {
  96. return 0;
  97. }
  98.  
  99. // --- 如果没有阻止,调用原始的 setInterval ---
  100. const intervalId = originalSetInterval.call(this, callback, delay, ...args);
  101. return intervalId;
  102. }
  103. } catch (error) {
  104. console.error('Error getting callback toString() or during string analysis:', error);
  105. }
  106.  
  107. // 确保浏览器支持 Navigation API
  108. try {
  109. if ('navigation' in window) {
  110.  
  111. window.navigation.addEventListener('navigate', (event) => {
  112. const destinationUrl = event.destination.url;
  113.  
  114. const destinationOrigin = new URL(destinationUrl).origin;
  115.  
  116. // Check if the destination origin is different from the current origin
  117. if (destinationOrigin !== originUrl) {
  118. console.warn(`阻止了到非同源地址的跳转: ${destinationUrl}`);
  119.  
  120. // Prevent the default navigation behavior
  121. // event.canIntercept must be true for preventDefault to work on this event type
  122. if (event.canIntercept) {
  123. event.preventDefault();;
  124. } else {
  125. console.log(`Navigation to ${destinationUrl} cannot be intercepted.`);
  126. // Note: Some navigations like target="_blank" might not be interceptable this way
  127. }
  128.  
  129.  
  130. } else {
  131. console.log(`允许同源跳转: ${destinationUrl}`);
  132. // Let the navigation proceed
  133. }
  134.  
  135. });
  136.  
  137. console.log(`当前页面源: ${window.location.origin}`);
  138. console.log('Navigation API 监听已启动...');
  139.  
  140. } else {
  141. console.warn('当前浏览器不支持 Navigation API,请考虑使用 click/submit 监听作为替代。');
  142. // Fallback to click/submit method if necessary
  143. }
  144.  
  145. } catch (e) {
  146. // Handle potential errors if the URL is invalid or cannot be parsed
  147. console.error('无法解析目标URL或发生错误:', e);
  148. // Decide whether to prevent or allow on error - usually allowing is safer
  149. // Let's assume allowing is the default if we can't verify
  150. }
  151.  
  152. function removeTargetBlankDivs() {
  153. try {
  154. const blankTargetAnchors = document.querySelectorAll('a[target="_blank"]');
  155. if (blankTargetAnchors.length === 0) {
  156. //console.log("----------------No target='_blank' anchors found.");
  157. return;
  158. }
  159.  
  160. blankTargetAnchors.forEach(anchor => {
  161. const parentDiv = anchor.closest('div');
  162. if (parentDiv) {
  163. if (parentDiv.parentNode) {
  164. //console.log("----------------Removing div: ", anchor.outerHTML);
  165. parentDiv.remove();
  166. }
  167. }
  168. });
  169. } catch (error) {
  170. console.error("----------------Error accessing or modifying content: ", error);
  171. }
  172. }
  173.  
  174. function removeAdElement() {
  175.  
  176. if (adEleId.length === 0 && adEleClass.length === 0 && adEleOther.length === 0) {
  177. return;
  178. }
  179.  
  180. const selectors = [];
  181. if (adEleId.length > 0) {
  182. selectors.push(...adEleId.map(id => `#${id}`));
  183. }
  184. if (adEleClass.length > 0) {
  185. selectors.push(...adEleClass.map(className => `.${className}`));
  186. }
  187. if (adEleOther.length > 0) {
  188. selectors.push(...adEleOther.map(otherEle => `${otherEle}`));
  189. }
  190. if (selectors.length === 0) {
  191. return;
  192. }
  193.  
  194. const combinedSelector = selectors.join(', ');
  195. try {
  196. const elementsToRemove = document.querySelectorAll(combinedSelector);
  197.  
  198. elementsToRemove.forEach(element => {
  199. // 使用 element.remove() 是现代且推荐的删除元素方法
  200. // 兼容性:IE(Edge 除外)不支持,但现代浏览器都支持
  201. if (element && typeof element.remove === 'function') {
  202. element.remove();
  203. // console.log("已删除元素:", element); // 可选:记录删除的元素
  204. } else if (element && element.parentNode) {
  205. // 兼容旧浏览器,通过父节点删除
  206. element.parentNode.removeChild(element);
  207. // console.log("已删除元素 (旧方法):", element); // 可选:记录删除的元素
  208. }
  209. });
  210. } catch(error) {
  211. console.error("删除元素时发生错误:", error);
  212. }
  213. }
  214.  
  215. removeTargetBlankDivs();
  216. removeAdElement();
  217.  
  218. // 考虑网速慢和卡顿的情况
  219. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 1000)
  220. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 2000)
  221. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 3000)
  222. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 5000)
  223. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 10000)
  224. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 20000)
  225. setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 30000)
  226.  
  227. try {
  228. window.addEventListener('load', () => {
  229. removeTargetBlankDivs();
  230. removeAdElement();
  231. })
  232. } catch (error) {
  233. console.error("监听页面load发生错误:", error);
  234. }
  235.  
  236. })();