spm_Track_Block_Tool

移除链接中的spm跟踪参数

目前为 2022-04-09 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name spm_Track_Block_Tool
  3. // @namespace _s7util__
  4. // @version 0.5.0
  5. // @description:en Remove [spm] track paramter in URL
  6. // @description 移除链接中的spm跟踪参数
  7. // @author shc0743
  8. // @match *://*/*
  9. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  10. // @grant none
  11. // @license GPL-3
  12. // @supportURL https://github.com/shc0743/MyUtility/issues/new
  13. // @run-at document-start
  14. // ==/UserScript==
  15.  
  16. /*
  17. Description:
  18. 说明:
  19.  
  20. This user script removes the spm paramter in <a href> elements.
  21. 此脚本移除 <a href> 元素中的spm参数。
  22. If it doesn't work, try refreshing it a few times or wait a while.
  23. 若无法生效,请尝试刷新几次或等一会。
  24.  
  25. Examples:
  26. 示例:
  27. https://www.bilibili.com/video/av170001?spm_id_from=114514
  28. -> https://www.bilibili.com/video/av170001
  29.  
  30. https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514&query2=data3
  31. -> https://www.bilibili.com/video/av170001?query1=arg2&query2=data3
  32.  
  33. https://www.bilibili.com/video/av170001?spm=114514.1919810#hash
  34. -> https://www.bilibili.com/video/av170001#hash
  35.  
  36. https://www.bilibili.com/video/av170001?spm=114514.1919810&query2=data3#hash1
  37. -> https://www.bilibili.com/video/av170001?query2=data3#hash1
  38. */
  39.  
  40. (function(window) {
  41. 'use strict';
  42.  
  43. // Your code here...
  44.  
  45. //var expr = /\?[\s\S]*spm/i;
  46. var track_args_list = [
  47. 'spm', 'spm_id_from', 'from_source'
  48. ];
  49. /**
  50. * 去除字符串中的spm参数
  51. * @param {String} str
  52. * @returns 去除spm后的结果
  53. */
  54. var remove_spm = function (str) {
  55. var newstr = '';
  56. var len = str.length;
  57. var is_in_query_part = false; // 只去除查询参数部分,避免正常url被替换而导致404
  58.  
  59. for (let i = 0; i < len; ++i) {
  60. if (str[i] == '?') is_in_query_part = true;
  61. if (!is_in_query_part) { // 时机未到,跳过
  62. newstr += str[i];
  63. continue;
  64. }
  65. let need_break = true;
  66. for (let j = 0; j < track_args_list.length; ++j) {
  67. need_break = true;
  68. if (track_args_list[j] == str.substring(i,
  69. i + track_args_list[j].length - 0)) {
  70. // 检测到 “spm”
  71. while ((++i) < len) {
  72. if (str[i] == '&') { // 不能单独保留一个 & 号
  73. i++; break; // 去掉
  74. }
  75. if (str[i] == '#') break; // 保留hash部分
  76. }
  77. if (i == len) break; // 越界,直接break,以免url出现undefined
  78. }
  79. need_break = false;
  80. }
  81. if (need_break) break;
  82. newstr += str[i]; //
  83. }
  84. /*
  85. @deprecated 此移除器不按预期工作
  86. */
  87. // newstr = str;
  88. // for (let i = 0; i < track_args_list.length; ++i) {
  89. // let index = newstr.indexOf(track_args_list[i] + '=');
  90. // if (index + 1) { // found
  91. // let par_end = newstr.indexOf('&', index);
  92. // if (par_end == 0)
  93. // par_end = newstr.indexOf('#', index);
  94. // let str1 = newstr.substr(0, index);
  95. // let str2 = newstr.substr(par_end);
  96. // newstr = str1 + str2;
  97. // }
  98. // }
  99.  
  100. var _lastchar;
  101. for (let i = 0; i < newstr.length; ++i) {
  102. _lastchar = newstr[newstr.length - 1];
  103. if (_lastchar == '?' || _lastchar == '&') { // 如果移除后只剩下 ? 或 &
  104. newstr = newstr.substr(0, newstr.length - 1); // 去掉
  105. _lastchar = newstr[newstr.length - 1];
  106. if (_lastchar == '?' || _lastchar == '&') // 再次检测
  107. newstr = newstr.substr(0, newstr.length - 1);
  108. } else break;
  109. }
  110. // Bug-Fix:
  111. // https://example.com/example?q1=arg&spm=123#hash1
  112. // -> https://example.com/example?q1=arg&#hash1
  113. // Invalid URL syntax at ^^
  114. newstr = newstr.replace(/\&\#/igm, '#');
  115. newstr = newstr.replace(/\?\#/igm, '#');
  116. return newstr;
  117. }
  118. var test_spm = function (str) {
  119. for (let i = 0; i < track_args_list.length; ++i)
  120. if (new RegExp(track_args_list[i], 'i').test(str))
  121. return true;
  122. return false;
  123. };
  124. var _realwindowopen = window.open;
  125.  
  126. var _link_click = function (event) {
  127. if (!(/http/i.test(this.href))) return;
  128. event.preventDefault();
  129. // 防止被再次加入spm
  130. this.href = remove_spm(this.href);
  131. _realwindowopen(this.href, this.target || '_self');
  132. return false;
  133. };
  134. var _link_mouseover = function () {
  135. if (test_spm(this.href))
  136. this.href = remove_spm(this.href);
  137. };
  138. var linkclickhandlerinit = function () {
  139. var el = document.querySelectorAll('a[href]');
  140. for (let i = el.length - 1; i >= 0; --i) {
  141. if (test_spm(el[i].href)) {
  142. // 链接已经被加入spm , 需要移除
  143. el[i].href = remove_spm(el[i].href);
  144. }
  145. el[i].removeEventListener('click', _link_click);
  146. el[i].addEventListener('click', _link_click, true);
  147. el[i].removeEventListener('mouseover', _link_mouseover);
  148. el[i].addEventListener('mouseover', _link_mouseover, false);
  149. }
  150. };
  151. window.addEventListener('load', function (event) {
  152. window.setInterval(linkclickhandlerinit, 5000);
  153. window.setTimeout(linkclickhandlerinit, 1000);
  154. window.setTimeout(linkclickhandlerinit, 500);
  155. window.setTimeout(linkclickhandlerinit, 1);
  156. try {
  157. Object.defineProperty(window, 'open', {
  158. value: function (url, target, features) {
  159. return _realwindowopen(
  160. remove_spm(url),
  161. target,
  162. features);
  163. },
  164. writable: false,
  165. enumerable: true,
  166. configurable: true
  167. }); // 重定义window.open 以阻止弹出窗口中的spm
  168. }
  169. catch (error) {
  170. console.warn("This browser doesn't support redefining" +
  171. " window.open , so [SpmBlockTool] cannot remove" +
  172. " spm in popup window.\nError:", error);
  173. }
  174. });
  175.  
  176. // 移除当前页面的spm
  177. // 当然,实际上spm已经在userscript加载前被发送到服务器,
  178. // 所以该功能仅美化url.
  179. // 如果要禁用该功能,删除下面一行开头的斜杠。
  180. //if(0)
  181. // Remove spm from current page
  182. // Of course, in fact, SPM has been sent to the server
  183. // before userscript is loaded, so this function only beautifies the URL.
  184. // If you want to disable this feature, remove the slash
  185. // at the beginning of the following line:
  186. //if(0)
  187. if (test_spm(location.href)) {
  188. window.history.replaceState({},
  189. document.title,
  190. remove_spm(location.href));
  191. }
  192.  
  193. /*
  194. var test_urls = [
  195. 'https://www.bilibili.com/video/BV18X4y1N7Yh',
  196. 'https://www.bilibili.com/video/BV18X4y1N7Yh?spm_id_from=114514',
  197. 'https://www.bilibili.com/video/BV18X4y1N7Yh?spm=114514.1919810',
  198. 'https://www.bilibili.com/video/BV18X4y1N7Yh?spm_id_from=114514.123',
  199.  
  200. 'https://www.bilibili.com/video/av170001',
  201. 'https://www.bilibili.com/video/av170001?spm_id_from=114514',
  202. 'https://www.bilibili.com/video/av170001?spm=114514.1919810',
  203. 'https://www.bilibili.com/video/av170001?spm_id_from=114514.123',
  204.  
  205. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514',
  206. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810',
  207. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514.123',
  208. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514',
  209. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810',
  210. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514.123',
  211.  
  212. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514&query2=data3',
  213. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810&query2=data3',
  214.  
  215. 'https://www.bilibili.com/video/av170001?spm_id_from=114514#hash',
  216. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514#hash1',
  217. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810#hash1',
  218.  
  219. 'https://www.bilibili.com/video/av170001?spm_id_from=114514&query2=data3#hash1',
  220. 'https://www.bilibili.com/video/av170001?spm=114514.1919810&query2=data3#hash1',
  221. ];
  222. for(let i=0;i<test_urls.length;++i){
  223. let el=document.createElement('a');
  224. el.href=test_urls[i];
  225. el.innerHTML=i+1 + '';
  226. document.documentElement.appendChild(el);
  227. }
  228. for(let i=0;i<test_urls.length;++i){
  229. let el=document.createElement('a');
  230. el.href=test_urls[i];
  231. el.innerHTML=i+1 + ' blank';
  232. el.target='_blank';
  233. document.documentElement.appendChild(el);
  234. }
  235. */
  236. })(window);