spm_Track_Block_Tool

移除链接中的spm跟踪参数

当前为 2022-04-09 提交的版本,查看 最新版本

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