Free Read And Go

链接直接跳转,阅读全文

安装此脚本?
作者推荐脚本

您可能也喜欢网盘有效性检查

安装此脚本
  1. // ==UserScript==
  2. // @name Free Read And Go
  3. // @namespace http://tampermonkey.net/
  4. // @version 2025.03.01
  5. // @description 链接直接跳转,阅读全文
  6. // @author Leon406
  7. // @match *://**/*
  8. // @run-at document-start
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=gf.qytechs.cn
  10. // @homepageURL https://github.com/Leon406/jsdelivr/tree/master/js/tampermonkey
  11. // @connect *
  12. // @grant GM_xmlhttpRequest
  13. // @exclude *://login.live.com/*
  14. // @exclude *://*.aliyun.com/*
  15. // @exclude *://*.google.*/*
  16. // @exclude *://pan.baidu.com/*
  17. // @exclude *://tieba.baidu.com/*
  18. // @exclude *://baike.baidu.com/*
  19. // @exclude *://leetcode.*/*
  20. // @exclude *://cloud.baidu.com/*
  21. // @exclude *://*.bce.baidu.com/*
  22. // @exclude *://*.iconfont.cn/*
  23. // @exclude *://*.sou.com/*
  24. // @exclude *://*.jiguang.cn/*
  25. // @exclude *://*.mozilla.org/*
  26. // @exclude https://space.bilibili.com/*
  27. // @exclude https://www.thepaper.cn/*
  28. // @license GPL-3.0 License
  29. // ==/UserScript==
  30.  
  31. const host = window.location.host;
  32. const rootHost = host.replaceAll(/.*\.(\w+\.\w+)$/g, "$1");
  33.  
  34. const REAL_GO = {
  35. "juejin.cn": {
  36. prefix: "https://link.juejin.cn/?target=",
  37. query: "target",
  38. action: urlDecode
  39. },
  40. "www.douban.com": {
  41. prefix: "https://www.douban.com/link2/",
  42. query: "url",
  43. action: urlDecode
  44. },
  45. "feishu.cn": {
  46. func: () => get_elements(".outer-u-container a", filterThirdATag).forEach(createNewTag)
  47. },
  48. "security.feishu.cn": {
  49. prefix: "https://security.feishu.cn/link/safety?",
  50. query: "target",
  51. action: urlDecode
  52. },
  53. "51.ruyo.net": {
  54. prefix: "https://51.ruyo.net/go/index.html?u=",
  55. query: "u",
  56. action: urlDecode
  57. },
  58. "blog.51cto.com": {
  59. prefix: "https://blog.51cto.com/transfer?",
  60. action: urlDecode,
  61. //func: () => get_elements(".article-content-wrap a", filterThirdATag).forEach(removeOnClick)
  62. },
  63. "zhuanlan.zhihu.com": {
  64. prefix: "https://link.zhihu.com/?target",
  65. query: "target",
  66. action: urlDecode
  67. },
  68. "www.zhihu.com": {
  69. prefix: "https://link.zhihu.com/?target",
  70. query: "target",
  71. action: urlDecode
  72. },
  73. "cloud.tencent.com": {
  74. prefix: "https://cloud.tencent.com/developer/tools/blog-entry?",
  75. query: "target",
  76. action: urlDecode
  77. },
  78. "gitee.com": {
  79. prefix: "https://gitee.com/link?target=",
  80. query: "target",
  81. action: urlDecode
  82. },
  83. "xie.infoq.cn": {
  84. prefix: "https://xie.infoq.cn/link?",
  85. query: "target",
  86. action: urlDecode,
  87. func: () => get_elements(".main a", filterThirdATag).forEach(createNewTag)
  88. },
  89. "sspai.com": {
  90. prefix: "https://sspai.com/link?",
  91. query: "target",
  92. action: urlDecode
  93. },
  94. "afdian.com": {
  95. prefix: "https://afdian.com/link?",
  96. query: "target",
  97. action: urlDecode
  98. },
  99. "www.oschina.net": {
  100. prefix: "https://www.oschina.net/action/GoToLink?",
  101. query: "url",
  102. action: urlDecode
  103. },
  104. "c.pc.qq.com": {
  105. prefix: "https://c.pc.qq.com/middlem.html?",
  106. query: "pfurl",
  107. action: urlDecode
  108. },
  109. "weibo.cn": {
  110. prefix: "https://weibo.cn/sinaurl?u=",
  111. query: "u",
  112. action: urlDecode
  113. },
  114. "aiqicha.baidu.com": {
  115. prefix: "https://aiqicha.baidu.com/safetip?",
  116. query: "target",
  117. action: rawText
  118. },
  119. "www.qcc.com": {
  120. prefix: "https://www.qcc.com/web/transfer-link?",
  121. query: "target",
  122. action: urlDecode
  123. },
  124. "www.tianyancha.com": {
  125. prefix: "https://www.tianyancha.com/security",
  126. query: "target",
  127. action: urlDecode
  128. },
  129. "leetcode.cn": {
  130. prefix: "https://leetcode.cn/link/?target=",
  131. query: "target",
  132. action: urlDecode
  133. },
  134. "www.jianshu.com": {
  135. prefix: "https://link.jianshu.com",
  136. query: "t",
  137. prefix2: "https://www.jianshu.com/go-wild",
  138. query2: "url",
  139. action: urlDecode
  140. },
  141. "yuque.com": {
  142. prefix: "https://www.yuque.com/r/goto?url=",
  143. query: "url",
  144. action: urlDecode
  145. },
  146. "nowcoder.com": {
  147. prefix: "https://hd.nowcoder.com/link.html?target=",
  148. query: "target",
  149. action: urlDecode
  150. },
  151.  
  152. "steamcommunity.com": {
  153. prefix: "https://steamcommunity.com/linkfilter/?url=",
  154. query: "url",
  155. action: urlDecode
  156. },
  157.  
  158. "docs.google.com": {
  159. prefix: "https://www.google.com/url?",
  160. query: "q",
  161. action: urlDecode
  162. },
  163. "t.me": {
  164. prefix: "https://t.me/iv?url=",
  165. query: "url",
  166. action: urlDecode
  167. },
  168. "telegra.ph": {
  169. prefix: "https://t.me/iv?url=",
  170. query: "url",
  171. action: urlDecode
  172. },
  173. "www.pixiv.net": {
  174. prefix: "https://www.pixiv.net/jump.php",
  175. query: "url",
  176. action: urlDecode
  177. },
  178. "www.youtube.com": {
  179. prefix: "https://www.youtube.com/redirect?",
  180. query: "q",
  181. action: urlDecode
  182. },
  183. "www.linkedin.com": {
  184. prefix: "https://www.linkedin.com/redir/redirect?",
  185. query: "url",
  186. action: urlDecode
  187. },
  188. "mail.qq.com": {
  189. prefix: "https://mail.qq.com/cgi-bin/readtemplate",
  190. query: "gourl",
  191. action: urlDecode,
  192. intervalFunc: () => get_elements("#contentDiv a", filterThirdATag).forEach(stopropagation)
  193. },
  194. "www.kdocs.cn": {
  195. prefix: "https://www.kdocs.cn/office/link?target=",
  196. query: "target",
  197. action: urlDecode
  198. },
  199. "bbs.nga.cn": {
  200. func: () => get_elements("#m_posts a", filterThirdATag).forEach(removeOnClick)
  201. },
  202. "nga.178.com": {
  203. func: () => get_elements("#m_posts a", filterThirdATag).forEach(removeOnClick)
  204. },
  205. "tieba.baidu.com": {
  206. prefix: "https://tieba.baidu.com/mo/q/checkurl?url=",
  207. query: "url",
  208. action: urlDecode,
  209. intervalFunc: () => get_elements("#container a", filterThirdATag).forEach(stopropagation)
  210. },
  211. "blog.csdn.net": {
  212. func: () => get_elements(".blog-content-box a", filterThirdATag).forEach(createNewTag)
  213. },
  214. "developers.weixin.qq.com": {
  215. prefix: "/community/middlepage/href?href=",
  216. query: "href",
  217. action: urlDecode,
  218. func: () => get_elements("a", filterThirdATag).forEach(stopropagation)
  219. }
  220. }
  221.  
  222. function filterThirdATag(aTag) {
  223. return aTag.href.startsWith("http") && !aTag.href.includes(rootHost)
  224. }
  225.  
  226. function find_all_iframe(doc = document) {
  227. let frame = doc.querySelectorAll("iframe");
  228. if (frame.length === 0)
  229. return [];
  230. let frames = Array.from(frame)
  231. .filter(el => el.contentDocument)
  232. if (frames.length > 0) {
  233. let frames2 = frames.flatMap(el => find_all_iframe(el.contentDocument))
  234. if (frames2.length > 0) {
  235. frames2.forEach(e => frames.push(e))
  236. }
  237. }
  238. return frames;
  239. }
  240.  
  241. function get_elements(selector, cond = el => el) {
  242. let elements = Array.from(document.querySelectorAll(selector)).filter(cond);
  243. if (elements.length === 0) {
  244. elements = find_all_iframe()
  245. .flatMap(el => Array.from(el.contentDocument.querySelectorAll(selector)))
  246. .filter(el => cond(el));
  247. }
  248. return elements;
  249. }
  250.  
  251. function get_elements_simlpe(selector, cond = el => el) {
  252. return Array.from(document.querySelectorAll(selector)).filter(cond);
  253. }
  254.  
  255. const reg_more = /^\s*(阅读|查看|展开)(全文|全部|更多)$|^展开(剩余|阅读)/g
  256.  
  257. function showMore() {
  258. var mores = get_elements_simlpe("a", el => reg_more.test(el.text) && el.target != '_blank');
  259. //console.log("showMore ", mores);
  260. for (let more of mores) {
  261. if (!more.href.startsWith("http") && more.href.includes(rootHost)) {
  262. more.click();
  263. }
  264. }
  265.  
  266. mores = get_elements_simlpe("span,div", el => reg_more.test(el.textContent));
  267. //console.log("showMore span ", mores);
  268. for (let more of mores) {
  269. let p = more.closest("a");
  270. if (p) {
  271. if (!p.href.startsWith("http") && p.href.includes(rootHost)) {
  272. more.click();
  273. }
  274. } else {
  275. more.click();
  276. }
  277. }
  278. }
  279. const stopEvent = (e) => {
  280. if (e.stopPropagation) {
  281. e.stopPropagation();
  282. }
  283. };
  284.  
  285. function stopropagation(aTag) {
  286. if (aTag.onclick && aTag.onclick != stopEvent)
  287. aTag.onclick = stopEvent
  288. }
  289.  
  290. function removeOnClick(aTag) {
  291. if (aTag.onclick)
  292. aTag.onclick = null;
  293. console.log("removeOnClick", aTag)
  294. aTag.removeEventListener("click", function () {});
  295. }
  296.  
  297. function createNewTag(aTag) {
  298. //console.log("rewriteOnClick", aTag)
  299. if (!aTag.onclick && aTag.href) {
  300. aTag.onclick = function antiRedirectOnClickFn(e) {
  301. e.stopPropagation();
  302. e.preventDefault();
  303. e.stopImmediatePropagation();
  304. console.log("stop__", aTag)
  305. const tmpA = document.createElement("a");
  306. tmpA.href = aTag.href;
  307. tmpA.target = "_blank";
  308. tmpA.click();
  309. };
  310. }
  311. }
  312.  
  313. function interval(func, period = 500) {
  314. //console.log("interval", func)
  315. setInterval(func, period)
  316. }
  317.  
  318. function urlDecode(aTag, query) {
  319. //console.log("urlDecode", query, aTag)
  320. let url = new URL(aTag.href);
  321. // console.log("urlDecode", url.searchParams.get(query), url.search.replace("?", ""))
  322. url = query && url.searchParams.get(query) || url.search.replace("?", "")
  323. try {
  324. url =decodeURIComponent(url)
  325. }catch(err) {
  326. }
  327. aTag.href = url
  328. }
  329.  
  330. function rawText(aTag, query) {
  331. console.log("rawText", query, aTag)
  332. aTag.href = query
  333. }
  334.  
  335. function request(aTag, query) {
  336. GM_xmlhttpRequest({
  337. method: "get",
  338. url: aTag.href,
  339. onload: function (response) {
  340. var myregexp = /u *= *"([^"]*)"/;
  341. var match = myregexp.exec(response.responseText);
  342. if (match != null) {
  343. result = match[1];
  344. aTag.href = result
  345. } else {
  346. result = "";
  347. }
  348. console.log("request", result)
  349. }
  350. });
  351.  
  352. }
  353.  
  354. function removeClick() {
  355. document.body.addEventListener('click', function (event) {
  356. var target = event.target || event.srcElement;
  357. if (target.nodeName.toLocaleLowerCase() === 'a') {
  358. if (event.preventDefault) {
  359. event.preventDefault();
  360. } else {
  361. window.event.returnValue = true;
  362. }
  363. var url = target.getAttribute("href")
  364. if (target.getAttribute("target") === '_blank') {
  365. window.open(url)
  366. } else {
  367. window.location.href = url
  368. }
  369. }
  370. });
  371. }
  372.  
  373. function findAllHref(rule = "http") {
  374. return get_elements("a", el => el.href.includes(rule))
  375. }
  376.  
  377. (function () {
  378. 'use strict';
  379. let rule = REAL_GO[host] || REAL_GO[rootHost];
  380. console.log("====rule 11", rule)
  381. if (rule && rule.prefix && window.location.href.startsWith(rule.prefix)) {
  382. let url = new URL(window.location.href);
  383. let targetUrl = decodeURIComponent(rule.query && url.searchParams.get(rule.query) || url.search.replace("?", ""));
  384. window.location.href = targetUrl.includes("://") ? targetUrl : ("https://" + targetUrl);
  385. console.log("redirect-------->", window.location.href)
  386. return;
  387. }
  388.  
  389. if (rule && rule.prefix2 && window.location.href.startsWith(rule.prefix2)) {
  390. let url = new URL(window.location.href);
  391. let targetUrl = decodeURIComponent(rule.query2 && url.searchParams.get(rule.query2) || url.search.replace("?", ""))
  392. window.location.href = targetUrl.includes("://") ? targetUrl : ("https://" + targetUrl);
  393. console.log("redirect2-------->", window.location.href)
  394. return;
  395. }
  396.  
  397. // 有的页面不触发 onload
  398. setTimeout(() => {
  399. showMore();
  400. }, 3000)
  401. window.onload = function () {
  402. showMore();
  403. setTimeout(() => {
  404. console.log("====rule", rule)
  405. if (rule) {
  406. rule.prefix && findAllHref(rule.prefix).forEach(el => {
  407. rule.action && rule.action(el, rule.query)
  408. });
  409. rule.prefix2 && findAllHref(rule.prefix2).forEach(el => {
  410. rule.action && rule.action(el, rule.query2)
  411. });
  412. rule.func && rule.func()
  413. rule.intervalFunc && interval(rule.intervalFunc)
  414. }
  415. }, 3000)
  416. }
  417. })();

QingJ © 2025

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