rBlock

移除一些网站用于数据统计的链接跳转,加快网站访问速度。

  1. // ==UserScript==
  2. // @name rBlock
  3. // @author nonoroazoro
  4. // @description 移除一些网站用于数据统计的链接跳转,加快网站访问速度。
  5. // @description:en Removes redirects of web sites.
  6. // @homepageURL https://github.com/nonoroazoro/firefox/tree/master/greasemonkey/rBlock
  7. // @namespace https://gf.qytechs.cn/zh-CN/scripts/20568-rblock
  8. // @grant none
  9. // @version 1.3.8
  10. // @run-at document-end
  11. // @include /^https?:\/\/(.+\.)?google\./
  12. // @include /^https?:\/\/(.+\.)?zhihu\./
  13. // @include https://forum.gamer.com.tw/*
  14. // ==/UserScript==
  15.  
  16. const rBlock = {
  17.  
  18. _blockers: [],
  19.  
  20. start()
  21. {
  22. this.init();
  23. for (const blocker of this._blockers)
  24. {
  25. blocker.start();
  26. }
  27. },
  28.  
  29. init()
  30. {
  31. this._blockers = [];
  32. const _host = window.location.host;
  33.  
  34. // 1. google
  35. if (/^(.+\.)?google\./.test(_host))
  36. {
  37. this._blockers.push({
  38. start()
  39. {
  40. // 1. for static pages.
  41. // when google instant predictions is disabled,
  42. // this blocker will only be called once.
  43. this._block();
  44.  
  45. // 2. for dynamic pages.
  46. // when google instant predictions is enabled,
  47. // this blocker will be call whenever the current page is updated.
  48. _observe(this._block);
  49. },
  50.  
  51. // block redirects of google
  52. _block()
  53. {
  54. // 1. general
  55. let elems = document.querySelectorAll(`a[href*="url="]`);
  56. revealURL(elems, /.*url=(http[^&]+)/i);
  57.  
  58. // 2. images
  59. elems = document.querySelectorAll(`a[jsaction][href]:not([href="javascript:void(0)"]):not(.rg_l)`);
  60. _removeAttributes(elems, "jsaction");
  61.  
  62. // 3. all/videos/news/apps
  63. elems = document.querySelectorAll(`a[onmousedown^="return rwt("]`);
  64. _removeAttributes(elems, "onmousedown");
  65.  
  66. // 4. cached links
  67. elems = document.querySelectorAll(`a[href^="http://webcache.googleusercontent."], a[href^="https://webcache.googleusercontent."]`);
  68. const targets = document.querySelectorAll(`a.rblock-cached-link`);
  69. if (elems.length !== targets.length * 2)
  70. {
  71. // prevent duplication
  72. let menuLink;
  73. let cacheLink;
  74. for (const elem of elems)
  75. {
  76. elem.style.display = "inline";
  77. menuLink = elem.closest("div.action-menu.ab_ctl");
  78.  
  79. cacheLink = document.createElement("a");
  80. cacheLink.setAttribute("href", elem.getAttribute("href").replace(/^http:/, "https:"));
  81. cacheLink.setAttribute("class", "rblock-cached-link");
  82. cacheLink.target = "_blank";
  83. cacheLink.innerText = " Cached ";
  84.  
  85. menuLink.parentNode.insertBefore(cacheLink, menuLink);
  86. }
  87. }
  88. }
  89. });
  90. }
  91.  
  92. // 2. zhihu
  93. if (/^(.+\.)?zhihu\./.test(_host))
  94. {
  95. this._blockers.push({
  96. start()
  97. {
  98. this._block();
  99. _observe(this._block);
  100. },
  101.  
  102. _block()
  103. {
  104. // 1. general
  105. revealURL(
  106. document.querySelectorAll(`a[href*="?target="]`),
  107. /.*target=(http[^&]+)/i
  108. );
  109.  
  110. // 2. open in new tab
  111. for (const elem of document.querySelectorAll(`a.internal`))
  112. {
  113. _openInNewTab(elem);
  114. }
  115. }
  116. });
  117. }
  118.  
  119. // 3. 巴哈姆特
  120. if (_host === "forum.gamer.com.tw")
  121. {
  122. this._blockers.push({
  123. start()
  124. {
  125. this._block();
  126. _observe(this._block);
  127. },
  128.  
  129. _block()
  130. {
  131. // 1. general
  132. revealURL(
  133. document.querySelectorAll(`a[href*="?url="]`),
  134. /.*url=(http.+)/i
  135. );
  136. }
  137. });
  138. }
  139. }
  140. };
  141.  
  142. function _observe(p_callback)
  143. {
  144. if (typeof p_callback === "function" && document.body)
  145. {
  146. (new window.MutationObserver(debounce(p_callback))).observe(document.body, { childList: true, subtree: true });
  147. }
  148. }
  149.  
  150. function _removeAttributes(p_elements, p_attributes)
  151. {
  152. if (p_elements && typeof p_attributes === "string")
  153. {
  154. const attributes = p_attributes.split(/\W+/) || [];
  155. for (const elem of p_elements)
  156. {
  157. for (const attr of attributes)
  158. {
  159. elem.removeAttribute(attr);
  160. }
  161. }
  162. }
  163. }
  164.  
  165. /* eslint no-unused-vars: "off" */
  166. function _removeListeners(p_element, p_events)
  167. {
  168. if (p_element && typeof p_events === "string")
  169. {
  170. const events = p_events.split(/\W+/) || [];
  171. for (const event of events)
  172. {
  173. p_element.removeEventListener(event, _preventDefaultAction, true);
  174. p_element.addEventListener(event, _preventDefaultAction, true);
  175. }
  176. }
  177. }
  178.  
  179. function _preventDefaultAction(e)
  180. {
  181. e.stopPropagation();
  182. }
  183.  
  184. function revealURL(p_elems, p_regex)
  185. {
  186. if (p_elems && p_regex)
  187. {
  188. let groups;
  189. for (const elem of p_elems)
  190. {
  191. // reveal url & open in new tab
  192. groups = decodeURIComponent(elem.getAttribute("href")).match(p_regex);
  193. if (groups && groups[1])
  194. {
  195. elem.setAttribute("href", groups[1]);
  196. _openInNewTab(elem);
  197. }
  198. }
  199. }
  200. }
  201.  
  202. function _openInNewTab(p_elem)
  203. {
  204. if (p_elem)
  205. {
  206. p_elem.target = "_blank";
  207. }
  208. }
  209.  
  210. function debounce(p_callback, p_delay = 500)
  211. {
  212. let timer = null;
  213. return function _inner(...args)
  214. {
  215. const context = this;
  216. window.clearTimeout(timer);
  217. timer = window.setTimeout(() =>
  218. {
  219. p_callback.apply(context, args);
  220. }, p_delay);
  221. };
  222. }
  223.  
  224. function throttle(p_callback, p_threshhold = 500, p_scope)
  225. {
  226. let last;
  227. let timer;
  228. return function _inner(...args)
  229. {
  230. const now = +new Date();
  231. const context = p_scope || this;
  232. if (last && now < last + p_threshhold)
  233. {
  234. window.clearTimeout(timer);
  235. timer = window.setTimeout(() =>
  236. {
  237. last = now;
  238. p_callback.apply(context, args);
  239. }, p_threshhold);
  240. }
  241. else
  242. {
  243. last = now;
  244. p_callback.apply(context, args);
  245. }
  246. };
  247. }
  248.  
  249. rBlock.start();

QingJ © 2025

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