// ==UserScript== // @name 自研 - 多个站点 - 反外站拦截 // @name:en_US Self-made - Multi-site - Anti-External Site Interception // @description 去除某些网站的外站拦截。目前已适配知乎、Pixiv(予素)、Gitee、天眼查、百度贴吧、插画世界、森空岛、新浪微博和豆瓣。 // @description:en_US Remove external site interception for some websites. Currently compatible with Zhihu, Pixiv, Gitee, TianYanCha, Baidu Tieba, Vlipix, skland, Sina Weibo, and Douban. // @version 1.0.6 // @author CPlayerCHN // @license MulanPSL-2.0 // @namespace https://www.gitlink.org.cn/CPlayerCHN // @match *://*.zhihu.com/* // @match *://www.pixiv.net/* // @match *://gitee.com/* // @match *://www.tianyancha.com/* // @match *://jump2.bdimg.com/safecheck/index // @match *://www.vilipix.com/* // @match *://www.skland.com/* // @match *://weibo.cn/sinaurl // @match *://weibo.com/* // @match *://m.weibo.cn/* // @match *://www.douban.com/* // @run-at document-start // @noframes // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 定义「配置」变量,「解码」「暂停执行」「点击器」函数。 const config = [ // { // "name": "站点名", // "matchLink": /匹配链接/, // "target": "目标", // "reproduce": "复现链接" // }, // 目标可用项:网页参数、元素选择符、自定义脚本`() => { {{自定义脚本}} }`和特殊方式。 // 特殊方式:`$entireParam`整个网页参数。 { "name": "知乎", "matchLink": /^link.zhihu.com/, "target": "target", "reproduce": ["https://www.zhihu.com/question/646179463/answer/3411700328", "https://zhuanlan.zhihu.com/p/102911463"] }, { "name": "Pixiv(予素)", "matchLink": /^www.pixiv.net\/jump.php/, "target": "$entireParam", "reproduce": "https://www.pixiv.net/users/10885193 > 查看个人资料" }, { "name": "Gitee", "matchLink": /^gitee.com\/link/, "target": "target", "reproduce": "https://gitee.com/rmbgame/SteamTools#从移动端-steam-app-导入令牌指南" }, { "name": "天眼查", "matchLink": /^www.tianyancha.com\/security/, "target": "target", "reproduce": "https://www.tianyancha.com/company/2347945472" }, { "name": "百度贴吧", "matchLink": /^jump2.bdimg.com\/safecheck\/index/, "target": ".warning_info a", "reproduce": "https://tieba.baidu.com/p/8459041179 > 5楼 > 彼梦Archi" }, { "name": "插画世界", "matchLink": /^www.vilipix.com\/jump/, "target": "$entireParam", "reproduce": "https://www.vilipix.com/illust/108871691" }, { "name": "森空岛", "matchLink": /^www.skland.com\/third-link/, "target": "target", "reproduce": "https://www.skland.com/ > 工具箱 > 塞壬唱片" }, { "name": "新浪微博", "matchLink": /^weibo.cn\/sinaurl/, "target": "u", "reproduce": ["https://weibo.com/3556190647/LfTSUxUB6", "https://weibo.com/2656274875/Ohfr4edHf", "https://m.weibo.cn/status/NiQw1CyCy"] }, { "name": "豆瓣", "matchLink": /^www.douban.com\/link2/, "target": "url", "reproduce": "https://www.douban.com/group/topic/253534825" } ]; function decode(data) { // 判断状况并解码。 // 内容数量为 4 的倍数且不是 `http(s)?` 开头的判断为 base64;内容开头是 `http(s)?` 的判断为 URI 编码。 if(data.length % 4 && !/^http(s)?/.test(data)) { return atob(data); }else if(/^http(s)?/.test(data)) { return decodeURIComponent(data); } }; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function clicker(elm) { // 定义「按钮元素」变量。 const btn = document.querySelector(elm); // 如果「按钮元素」存在就点击,不存在就等待 .1 秒后再次判断。 if(btn) { btn.click(); }else { await sleep(100); clicker(elm); } }; // 遍历「配置」。 config.forEach((data) => { // 当链接匹配,就判断目标执行方法并执行对应操作。 if(data.matchLink.test(location.href.replace(/http(s)?:\/\//, ""))) { // 定义「目标」变量。 const target = data.target; // 判断状况执行对应语句。 // 内容为字符串且包含 `(.#])` 的判断为元素选择符;内容为字符串且内容为判断为特殊方式;内容为字符串判断为网页参数;内容为函数判断为自定义脚本。 if(typeof target === "string" && /\.|#|\]/.test(target)) { clicker(target); }else if(typeof target === "string" && location.search !== "" && target === "$entireParam") { // 停止网页继续加载。 window.stop(); // 访问页面。 window.open(decode(location.search.substring(1)), "_self"); }else if(typeof target === "string" && location.search !== "") { // 停止网页继续加载。 window.stop(); // 定义「网页参数」变量。 const params = new URLSearchParams(location.search.substring(1)); // 访问页面。 window.open(decode(params.get(target)), "_self"); }else if(typeof target === "function") { target(); } } }); // 定义「侦测器」变量。 const observer = new MutationObserver(() => { // 遍历所有未被修改的链接元素。 document.querySelectorAll('a:not(.removeIntercepted)').forEach((link) => { // 遍历「配置」 config.forEach((data) => { // 定义「目标」变量。 const target = data.target; // 当链接元素地址与目标链接匹配、类型为字符串、内容不包含`(.#])`且不是空内容,就判断目标执行方法并执行对应操作。 if(data.matchLink.test(link.href.replace(/http(s)?:\/\//, "")) && typeof target === "string" && !/\.|#|\]/.test(target) && new URL(link.href).search !== "") { if(target === "$entireParam") { // 修改链接地址。 link.href = decode(new URL(link.href).search.substring(1)); }else { // 定义「网页参数」变量。 const params = new URLSearchParams(new URL(link.href).search.substring(1)); // 修改链接地址。 link.href = decode(params.get(target)); } // 添加「removeIntercepted」类,防止重复检测。 link.classList.add("removeIntercepted"); } }); }); }); // 当页面完成解析,就配置「侦测器」侦测目标节点。 document.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { "subtree": true, "childList": true }); }); })();