spm_Track_Block_Tool

移除链接中的spm跟踪参数

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

  1. // ==UserScript==
  2. // @name spm_Track_Block_Tool
  3. // @namespace _s7util__
  4. // @version 0.5.3
  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);
  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++;
  82. break; // 去掉
  83. }
  84. if (str[i] == '#') break; // 保留hash部分
  85. }
  86. if (i == len) break; // 越界,直接break,以免url出现undefined
  87. }
  88. need_break = false;
  89. }
  90. if (need_break) break;
  91. newstr += str[i]; //
  92. }
  93.  
  94. var _lastchar;
  95. for (let i = 0; i < newstr.length; ++i) {
  96. _lastchar = newstr[newstr.length - 1];
  97. if (_lastchar == '?' || _lastchar == '&') { // 如果移除后只剩下 ? 或 &
  98. newstr = newstr.substr(0, newstr.length - 1); // 去掉
  99. } else break;
  100. }
  101. // Bug-Fix:
  102. // https://example.com/example?q1=arg&spm=123#hash1
  103. // -> https://example.com/example?q1=arg&#hash1
  104. // Invalid URL syntax at ^^
  105. newstr = newstr.replace(/\&\#/igm, '#');
  106. newstr = newstr.replace(/\?\#/igm, '#');
  107. return newstr;
  108. }
  109. var test_spm = function (str) {
  110. for (let tracker of track_args_list)
  111. if (new RegExp(tracker, 'i').test(str))
  112. return true;
  113. return false;
  114. };
  115. var _realwindowopen = window.open;
  116.  
  117. var _link_click = function (event) {
  118. if (!(/http/i.test(this.href))) return;
  119. event.preventDefault();
  120. // 防止被再次加入spm
  121. this.href = remove_spm(this.href);
  122. _realwindowopen(this.href, this.target || '_self');
  123. return false;
  124. };
  125. var _link_mouseover = function () {
  126. if (test_spm(this.href))
  127. this.href = remove_spm(this.href);
  128. };
  129. var linkclickhandlerinit = function () {
  130. var el = document.querySelectorAll('a[href]');
  131. for (let i = el.length - 1; i >= 0; --i) {
  132. if (test_spm(el[i].href)) {
  133. // 链接已经被加入spm , 需要移除
  134. el[i].href = remove_spm(el[i].href);
  135. }
  136. el[i].removeEventListener('click', _link_click);
  137. el[i].addEventListener('click', _link_click, true);
  138. el[i].removeEventListener('mouseover', _link_mouseover);
  139. el[i].addEventListener('mouseover', _link_mouseover, false);
  140. }
  141. };
  142. window.addEventListener('load', function (event) {
  143. window.setInterval(linkclickhandlerinit, 5000);
  144. window.setTimeout(linkclickhandlerinit, 1000);
  145. window.setTimeout(linkclickhandlerinit, 500);
  146. window.setTimeout(linkclickhandlerinit, 1);
  147. try {
  148. Object.defineProperty(window, 'open', {
  149. value: function (url, target, features) {
  150. return _realwindowopen(
  151. remove_spm(url),
  152. target,
  153. features);
  154. },
  155. writable: false,
  156. enumerable: true,
  157. configurable: true
  158. }); // 重定义window.open 以阻止弹出窗口中的spm
  159. }
  160. catch (error) {
  161. console.warn("This browser doesn't support redefining" +
  162. " window.open , so [SpmBlockTool] cannot remove" +
  163. " spm in popup window.\nError:", error);
  164. }
  165. });
  166.  
  167. // 移除当前页面的spm
  168. // 当然,实际上spm已经在userscript加载前被发送到服务器,
  169. // 所以该功能仅美化url.
  170. // 如果要禁用该功能,删除下面一行开头的斜杠。
  171. //if(0)
  172. // Remove spm from current page
  173. // Of course, in fact, SPM has been sent to the server
  174. // before userscript is loaded, so this function only beautifies the URL.
  175. // If you want to disable this feature, remove the slash
  176. // at the beginning of the following line:
  177. //if(0)
  178. if (test_spm(location.href)) {
  179. window.history.replaceState({},
  180. document.title,
  181. remove_spm(location.href));
  182. }
  183.  
  184. /*
  185. var test_urls = [
  186. 'https://www.bilibili.com/video/BV18X4y1N7Yh',
  187. 'https://www.bilibili.com/video/BV18X4y1N7Yh?spm_id_from=114514',
  188. 'https://www.bilibili.com/video/BV18X4y1N7Yh?spm=114514.1919810',
  189. 'https://www.bilibili.com/video/BV18X4y1N7Yh?spm_id_from=114514.123',
  190. 'https://www.bilibili.com/video/av170001',
  191. 'https://www.bilibili.com/video/av170001?spm_id_from=114514',
  192. 'https://www.bilibili.com/video/av170001?spm=114514.1919810',
  193. 'https://www.bilibili.com/video/av170001?spm_id_from=114514.123',
  194. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514',
  195. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810',
  196. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514.123',
  197. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514',
  198. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810',
  199. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514.123',
  200. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514&query2=data3',
  201. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810&query2=data3',
  202. 'https://www.bilibili.com/video/av170001?spm_id_from=114514#hash',
  203. 'https://www.bilibili.com/video/av170001?query1=arg2&spm_id_from=114514#hash1',
  204. 'https://www.bilibili.com/video/av170001?query1=arg2&spm=114514.1919810#hash1',
  205. 'https://www.bilibili.com/video/av170001?spm_id_from=114514&query2=data3#hash1',
  206. 'https://www.bilibili.com/video/av170001?spm=114514.1919810&query2=data3#hash1',
  207. ];
  208. for(let i=0;i<test_urls.length;++i){
  209. let el=document.createElement('a');
  210. el.href=test_urls[i];
  211. el.innerHTML=i+1 + '';
  212. document.documentElement.appendChild(el);
  213. }
  214. for(let i=0;i<test_urls.length;++i){
  215. let el=document.createElement('a');
  216. el.href=test_urls[i];
  217. el.innerHTML=i+1 + ' blank';
  218. el.target='_blank';
  219. document.documentElement.appendChild(el);
  220. }
  221. */
  222.  
  223. })(window, [
  224. { 'domain': '*', 'keyword': 'spm' },
  225. { 'domain': '*', 'keyword': 'spm_id_from' },
  226. { 'domain': '*', 'keyword': 'from_source' },
  227. { 'domain': 'music.163.com', 'keyword': 'market' },
  228. ]);