自研 - 多个站点 - 反外站拦截

去除某些网站的外站拦截。目前已适配 16 个站点。

  1. // ==UserScript==
  2. // @name 自研 - 多个站点 - 反外站拦截
  3. // @name:en_US Self-made - Multi-site - Anti-External Site Interception
  4. // @description 去除某些网站的外站拦截。目前已适配 16 个站点。
  5. // @description:en_US Remove external site interception for some websites. Currently adapted for 16 sites.
  6. // @version 1.0.14
  7. // @author CPlayerCHN
  8. // @license MulanPSL-2.0
  9. // @namespace https://www.gitlink.org.cn/CPlayerCHN
  10. // @match *://*.zhihu.com/*
  11. // @match *://www.pixiv.net/*
  12. // @match *://gitee.com/*
  13. // @match *://www.tianyancha.com/*
  14. // @match *://jump2.bdimg.com/safecheck/index
  15. // @match *://www.vilipix.com/*
  16. // @match *://www.skland.com/*
  17. // @match *://weibo.cn/sinaurl
  18. // @match *://weibo.com/*
  19. // @match *://m.weibo.cn/*
  20. // @match *://www.douban.com/*
  21. // @match *://addons.mozilla.org/*
  22. // @match *://www.mcmod.cn/*
  23. // @match *://link.mcmod.cn/target/*
  24. // @match *://www.curseforge.com/*
  25. // @match *://cn.bing.com/search
  26. // @match *://www.gcores.com/*
  27. // @match *://sspai.com/*
  28. // @match *://www.bookmarkearth.cn/view/*
  29. // @run-at document-start
  30. // @noframes
  31. // ==/UserScript==
  32.  
  33. (function() {
  34. 'use strict';
  35.  
  36. // 定义「配置」变量,「解码」「暂停执行」「点击器」函数。
  37. const config = [
  38. // {
  39. // "name": "站点名",
  40. // "matchLink": /匹配链接/,
  41. // "target": "目标",
  42. // "reproduce": "复现链接"
  43. // },
  44. // 目标可用项:网页参数、元素选择符、自定义脚本`() => { {{自定义脚本}} }`、正则剔除和特殊方式。
  45. // 特殊方式:`$entireParam`整个网页参数。
  46. {
  47. "name": "知乎",
  48. "matchLink": /^link.zhihu.com/,
  49. "target": "target",
  50. "reproduce": ["https://www.zhihu.com/question/646179463/answer/3411700328", "https://zhuanlan.zhihu.com/p/102911463"]
  51. },
  52. {
  53. "name": "Pixiv(予素)",
  54. "matchLink": /^www.pixiv.net\/jump.php/,
  55. "target": "$entireParam",
  56. "reproduce": "https://www.pixiv.net/users/10885193 > 查看个人资料"
  57. },
  58. {
  59. "name": "Gitee",
  60. "matchLink": /^gitee.com\/link/,
  61. "target": "target",
  62. "reproduce": "https://gitee.com/rmbgame/SteamTools#从移动端-steam-app-导入令牌指南"
  63. },
  64. {
  65. "name": "天眼查",
  66. "matchLink": /^www.tianyancha.com\/security/,
  67. "target": "target",
  68. "reproduce": "https://www.tianyancha.com/company/2347945472"
  69. },
  70. {
  71. "name": "百度贴吧",
  72. "matchLink": /^jump2.bdimg.com\/safecheck\/index/,
  73. "target": ".warning_info a",
  74. "reproduce": "https://tieba.baidu.com/p/8459041179 > 5楼 > 彼梦Archi"
  75. },
  76. {
  77. "name": "插画世界",
  78. "matchLink": /^www.vilipix.com\/jump/,
  79. "target": "$entireParam",
  80. "reproduce": "https://www.vilipix.com/illust/108871691"
  81. },
  82. {
  83. "name": "森空岛",
  84. "matchLink": /^www.skland.com\/third-link/,
  85. "target": "target",
  86. "reproduce": "https://www.skland.com/ > 工具箱 > 塞壬唱片"
  87. },
  88. {
  89. "name": "新浪微博",
  90. "matchLink": /^weibo.cn\/sinaurl/,
  91. "target": "u",
  92. "reproduce": ["https://weibo.com/3556190647/LfTSUxUB6", "https://weibo.com/2656274875/Ohfr4edHf", "https://m.weibo.cn/status/NiQw1CyCy"]
  93. },
  94. {
  95. "name": "豆瓣",
  96. "matchLink": /^www.douban.com\/link2/,
  97. "target": "url",
  98. "reproduce": "https://www.douban.com/group/topic/253534825"
  99. },
  100. {
  101. "name": "Firefox 附加组件",
  102. "matchLink": /^addons.mozilla.org\/[a-z]{2}(-[A-Z]{2})?/,
  103. "target": () => {
  104.  
  105. // 当页面完成解析,就遍历所有链接元素如果是拦截页面就重配置为原链接。
  106. document.addEventListener('DOMContentLoaded', () => {
  107.  
  108. document.querySelectorAll("a").forEach((link) => {
  109.  
  110. if(/^https:\/\/prod\.outgoing\.prod\.webservices\.mozgcp\.net\/v1\/[a-z0-9]{64}\//.test(link.href)) {
  111.  
  112. link.href = decode(link.href.slice(118));
  113.  
  114. }
  115.  
  116. });
  117.  
  118. });
  119.  
  120. },
  121. "reproduce": "https://addons.mozilla.org/zh-CN/firefox/addon/noscript/"
  122. },
  123. {
  124. "name": "MC百科(MCMOD)",
  125. "matchLink": /^(link|www).mcmod.cn(\/target\/)?/,
  126. "target": /http(s)?:\/\/link.mcmod.cn\/target\//,
  127. "reproduce": "https://www.mcmod.cn/class/4170.html"
  128. },
  129. {
  130. "name": "curseForge",
  131. "matchLink": /^www.curseforge.com\/linkout/,
  132. "target": "remoteUrl",
  133. "reproduce": "https://www.curseforge.com/minecraft/mc-mods/timeless-and-classics-zero"
  134. },
  135. {
  136. "name": "中国必应",
  137. "matchLink": /^cn.bing.com\/search/,
  138. "target": () => {
  139.  
  140. // 当页面完成解析就遍历主体部分所有链接,如果是打开拦截页面就修改链接
  141. document.addEventListener('DOMContentLoaded', () => {
  142.  
  143. document.querySelectorAll("#b_content a").forEach((link) => {
  144.  
  145. if(/https:\/\/www.bing.com\/ck\/a/.test(link.href)) {
  146.  
  147. link.href = atob(link.href.split("&u=a1")[1].split("&ntb=1")[0].replaceAll(/[-_+]/g), "").split("#:")[0];
  148.  
  149. }
  150.  
  151. });
  152.  
  153. });
  154.  
  155. },
  156. "reproduce": "https://cn.bing.com/search?q=test"
  157. },
  158. {
  159. "name": "机核",
  160. "matchLink": /^www.gcores.com\/link/,
  161. "target": "target",
  162. "reproduce": "https://www.gcores.com/articles/158806"
  163. },
  164. {
  165. "name": "少数派",
  166. "matchLink": /^sspai.com\/link/,
  167. "target": "target",
  168. "reproduce": "https://sspai.com/post/89743"
  169. },
  170. {
  171. "name": "书签地球",
  172. "matchLink": /^www.bookmarkearth.cn\/view/,
  173. "target": () => {
  174.  
  175. // 当页面完成解析就遍历主体部分所有链接,如果是打开拦截页面就修改链接
  176. document.addEventListener("DOMContentLoaded", () => {
  177.  
  178. location.href = document.querySelector(".wrapper").dataset.url;
  179.  
  180. });
  181.  
  182. },
  183. "reproduce": ["https://www.bookmarkearth.cn/view/817eb92893d711edb9f55254005bdbf9", "https://www.bookmarkearth.cn/view/7df2a2b293d711edb9f55254005bdbf9"]
  184. },
  185. ];
  186.  
  187. function decode(data) {
  188.  
  189. // 判断状况并解码。
  190. // 内容数量为 4 的倍数且不是 `http(s)?` 开头的判断为 base64;内容开头是 `http(s)?` 的判断为 URI 编码。
  191. if(data.length % 4 === 0 && !/^http(s)?/.test(data)) {
  192.  
  193. return atob(data);
  194.  
  195. }else if(/^http(s)?/.test(data)) {
  196.  
  197. return decodeURIComponent(data);
  198.  
  199. }
  200.  
  201. };
  202.  
  203. function sleep(ms) {
  204.  
  205. return new Promise(resolve => setTimeout(resolve, ms));
  206.  
  207. }
  208.  
  209. async function clicker(elm) {
  210.  
  211. // 定义「按钮元素」变量。
  212. const btn = document.querySelector(elm);
  213.  
  214. // 如果「按钮元素」存在就点击,不存在就等待 .1 秒后再次判断。
  215. if(btn) {
  216.  
  217. btn.click();
  218.  
  219. }else {
  220.  
  221. await sleep(100);
  222. clicker(elm);
  223.  
  224. }
  225.  
  226. };
  227.  
  228.  
  229. // 遍历「配置」。
  230. config.forEach((data) => {
  231.  
  232. // 当链接匹配,就判断目标执行方法并执行对应操作。
  233. if(data.matchLink.test(location.href.replaceAll(/http(s)?:\/\//g, ""))) {
  234.  
  235. // 定义「目标」变量。
  236. const target = data.target;
  237.  
  238. // 判断状况执行对应语句。
  239. // 内容为字符串且包含 `(.#])` 的判断为元素选择符;内容为字符串且内容为判断为特殊方式;内容为字符串判断为网页参数;内容为正则表达式且页面链接与「目标匹配」判断为正则剔除;内容为函数判断为自定义脚本。
  240. if(typeof target === "string" && /\.|#|\]/.test(target)) {
  241.  
  242. clicker(target);
  243.  
  244. }else if(typeof target === "string" && location.search !== "" && target === "$entireParam") {
  245.  
  246. // 停止网页继续加载。
  247. window.stop();
  248.  
  249. // 访问页面。
  250. window.open(decode(location.search.substring(1)), "_self");
  251.  
  252. }else if(typeof target === "string" && location.search !== "") {
  253.  
  254. // 停止网页继续加载。
  255. window.stop();
  256.  
  257. // 定义「网页参数」变量。
  258. const params = new URLSearchParams(location.search.substring(1));
  259.  
  260. // 访问页面。
  261. window.open(decode(params.get(target)), "_self");
  262.  
  263. }else if(Object.prototype.toString.call(target) === "[object RegExp]" && target.test(location.href)) {
  264.  
  265. // 停止网页继续加载。
  266. window.stop();
  267.  
  268. // 定义「网页链接」变量。
  269. const URL = location.href.replace(target, "");
  270.  
  271. // 访问页面。
  272. window.open(decode(URL), "_self");
  273.  
  274. }else if(typeof target === "function") {
  275.  
  276. target();
  277.  
  278. }
  279.  
  280. }
  281.  
  282. });
  283.  
  284.  
  285. // 定义「侦测器」变量。
  286. const observer = new MutationObserver(() => {
  287.  
  288. // 遍历所有未被修改的链接元素。
  289. document.querySelectorAll('a:not(.removeIntercepted)').forEach((link) => {
  290.  
  291. // 遍历「配置」
  292. config.forEach((data) => {
  293.  
  294. // 定义「目标」变量。
  295. const target = data.target;
  296.  
  297. // 当链接元素地址与目标链接匹配、类型为字符串、内容不包含`(.#])`且不是空内容,就判断目标执行方法并执行对应操作。
  298. if(data.matchLink.test(link.href.replaceAll(/http(s)?:\/\//g, "")) && typeof target === "string" && !/\.|#|\]/.test(target) && new URL(link.href).search !== "") {
  299.  
  300. if(target === "$entireParam") {
  301.  
  302. // 修改链接地址。
  303. link.href = decode(new URL(link.href).search.substring(1));
  304.  
  305. }else {
  306.  
  307. // 定义「网页参数」变量。
  308. const params = new URLSearchParams(new URL(link.href).search.substring(1));
  309.  
  310. // 修改链接地址。
  311. link.href = decode(params.get(target));
  312.  
  313. }
  314.  
  315. // 添加「removeIntercepted」类,防止重复检测。
  316. link.classList.add("removeIntercepted");
  317.  
  318. // 当链接元素地址与目标链接匹配、类型为正则表达式且「目标」链接与元素链接匹配
  319. }else if (data.matchLink.test(link.href.replaceAll(/http(s)?:\/\//g, "")) && Object.prototype.toString.call(target) === "[object RegExp]" && target.test(link.href)) {
  320.  
  321. // 定义「网页链接」变量。
  322. const URL = link.href.replace(target, "");
  323.  
  324. // 修改链接地址。
  325. link.href = decode(URL);
  326.  
  327. }
  328.  
  329. });
  330.  
  331. });
  332.  
  333. });
  334.  
  335. // 当页面完成解析,就配置「侦测器」侦测目标节点。
  336. document.addEventListener('DOMContentLoaded', () => {
  337.  
  338. observer.observe(document.body, {
  339. "subtree": true,
  340. "childList": true
  341. });
  342.  
  343. });
  344.  
  345. })();

QingJ © 2025

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