自动无缝翻页

自动无缝翻页,目前支持:423Down、Apphot(原烈火汉化)、小众软件

当前为 2021-02-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 自动无缝翻页
  3. // @version 1.1.2
  4. // @author X.I.U
  5. // @description 自动无缝翻页,目前支持:423Down、Apphot(原烈火汉化)、小众软件
  6. // @match *://www.423down.com/*
  7. // @exclude *://www.423down.com/*.html
  8. // @match *://apphot.cc/*
  9. // @exclude *://apphot.cc/*.html
  10. // @match *://www.appinn.com/
  11. // @match *://www.appinn.com/*/*/
  12. // @match *://www.appinn.com/?s=*
  13. // @icon https://s3.ax1x.com/2021/02/25/yj2s4f.png
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_registerMenuCommand
  16. // @grant GM_openInTab
  17. // @license GPL-3.0 License
  18. // @run-at document-end
  19. // @namespace https://github.com/XIU2/UserScript
  20. // ==/UserScript==
  21.  
  22. (function() {
  23. // 注册脚本菜单
  24. GM_registerMenuCommand('反馈 & 申请添加支持', function () {window.GM_openInTab('https://github.com/XIU2/UserScript#xiu2userscript', {active: true,insert: true,setParent: true});});
  25.  
  26. // 默认 ID 为 0
  27. var curSite = {SiteTypeID: 0};
  28.  
  29. // 自动翻页规则
  30. let DBSite = {
  31. postslist_423down: {
  32. SiteTypeID: 1,
  33. pager: {
  34. nextLink: '//div[@class="paging"]//a[contains(text(),"下一页")][@href]',
  35. pageElement: 'css;div.content-wrap ul.excerpt > li',
  36. HT_insert: ['css;div.content-wrap ul.excerpt', 2],
  37. replaceE: 'css;div.paging',
  38. scrollDelta: 1500
  39. }
  40. },
  41. postslist_apphot: {
  42. SiteTypeID: 2,
  43. pager: {
  44. nextLink: '//div[@class="pagination"]//a[contains(text(),"下一页")][@href]',
  45. pageElement: 'css;div.content > article.excerpt',
  46. HT_insert: ['css;div.pagination', 1],
  47. replaceE: 'css;div.pagination',
  48. scrollDelta: 1500
  49. }
  50. },
  51. postslist_appinn: {
  52. SiteTypeID: 3,
  53. pager: {
  54. nextLink: '//a[@class="next page-numbers"][@href]',
  55. pageElement: 'css;section#latest-posts > article',
  56. HT_insert: ['css;nav.navigation.pagination', 1],
  57. replaceE: 'css;div.nav-links',
  58. scrollDelta: 1500
  59. }
  60. }
  61. };
  62.  
  63. // 用于脚本内部判断当前 URL 类型
  64. let SiteType = {
  65. POSTSLIST_423DOWN: DBSite.postslist_423down.SiteTypeID,
  66. POSTSLIST_APPHOT: DBSite.postslist_apphot.SiteTypeID,
  67. POSTSLIST_APPINN: DBSite.postslist_appinn.SiteTypeID
  68. };
  69.  
  70. switch (location.host) {
  71. case "www.423down.com":
  72. curSite = DBSite.postslist_423down;
  73. break;
  74. case "apphot.cc":
  75. curSite = DBSite.postslist_apphot;
  76. break;
  77. case "www.appinn.com":
  78. curSite = DBSite.postslist_appinn;
  79. break;
  80. }
  81. curSite.pageUrl = ""; // 下一页URL
  82. pageLoading(); // 自动无缝翻页
  83.  
  84.  
  85. // 自动无缝翻页
  86. function pageLoading() {
  87. if (curSite.SiteTypeID > 0){
  88. windowScroll(function (direction, e) {
  89. if (direction === "down") { // 下滑才准备翻页
  90. var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
  91. console.log(document.documentElement.scrollHeight)
  92. let scrollDelta = curSite.pager.scrollDelta;
  93. if (document.documentElement.scrollHeight <= document.documentElement.clientHeight + scrollTop + scrollDelta) {
  94. ShowPager.loadMorePage();
  95. }
  96. }
  97. });
  98. }
  99. }
  100.  
  101.  
  102. // 滚动条事件
  103. function windowScroll(fn1) {
  104. var beforeScrollTop = document.documentElement.scrollTop,
  105. fn = fn1 || function () {};
  106. setTimeout(function () { // 延时执行,避免刚载入到页面就触发翻页事件
  107. window.addEventListener("scroll", function (e) {
  108. var afterScrollTop = document.documentElement.scrollTop,
  109. delta = afterScrollTop - beforeScrollTop;
  110. if (delta == 0) return false;
  111. fn(delta > 0 ? "down" : "up", e);
  112. beforeScrollTop = afterScrollTop;
  113. }, false);
  114. }, 1000)
  115. }
  116.  
  117.  
  118. var ShowPager = { // 修改自 https://greasyfork.org/scripts/14178
  119. getFullHref: function (e) {
  120. if(e == null) return '';
  121. "string" != typeof e && (e = e.getAttribute("href"));
  122. var t = this.getFullHref.a;
  123. return t || (this.getFullHref.a = t = document.createElement("a")), t.href = e, t.href;
  124. },
  125. createDocumentByString: function (e) {
  126. if (e) {
  127. if ("HTML" !== document.documentElement.nodeName) return (new DOMParser).parseFromString(e, "application/xhtml+xml");
  128. var t;
  129. try {
  130. t = (new DOMParser).parseFromString(e, "text/html");
  131. } catch (e) {
  132. }
  133. if (t) return t;
  134. if (document.implementation.createHTMLDocument) t = document.implementation.createHTMLDocument("ADocument"); else try {
  135. (t = document.cloneNode(!1)).appendChild(t.importNode(document.documentElement, !1)),
  136. t.documentElement.appendChild(t.createElement("head")), t.documentElement.appendChild(t.createElement("body"));
  137. } catch (e) {
  138. }
  139. if (t) {
  140. var r = document.createRange();
  141. r.selectNodeContents(document.body);
  142. var n = r.createContextualFragment(e);
  143. t.body.appendChild(n);
  144. for (var a, o = {
  145. TITLE: !0,
  146. META: !0,
  147. LINK: !0,
  148. STYLE: !0,
  149. BASE: !0
  150. }, i = t.body, s = i.childNodes, c = s.length - 1; c >= 0; c--) o[(a = s[c]).nodeName] && i.removeChild(a);
  151. return t;
  152. }
  153. } else console.error("没有找到要转成DOM的字符串");
  154. },
  155. loadMorePage: function () {
  156. if (curSite.pager) {
  157. let curPageEle = getElementByXpath(curSite.pager.nextLink);
  158. var url = this.getFullHref(curPageEle);
  159. //console.log(`${url} ${curPageEle} ${curSite.pageUrl}`);
  160. if(url === '') return;
  161. if(curSite.pageUrl === url) return;// 不会重复加载相同的页面
  162. curSite.pageUrl = url;
  163. // 读取下一页的数据
  164. curSite.pager.startFilter && curSite.pager.startFilter();
  165. GM_xmlhttpRequest({
  166. url: url,
  167. method: "GET",
  168. timeout: 5000,
  169. onload: function (response) {
  170. try {
  171. var newBody = ShowPager.createDocumentByString(response.responseText);
  172. let pageElems = getAllElements(curSite.pager.pageElement, newBody, newBody);
  173. let toElement = getAllElements(curSite.pager.HT_insert[0])[0];
  174. if (pageElems.length >= 0) {
  175. let addTo = "beforeend";
  176. if (curSite.pager.HT_insert[1] == 1) addTo = "beforebegin";
  177. // 插入新页面元素
  178. pageElems.forEach(function (one) {
  179. toElement.insertAdjacentElement(addTo, one);
  180. });
  181. // 替换待替换元素
  182. try {
  183. let oriE = getAllElements(curSite.pager.replaceE);
  184. let repE = getAllElements(curSite.pager.replaceE, newBody, newBody);
  185. if (oriE.length === repE.length) {
  186. for (var i = 0; i < oriE.length; i++) {
  187. oriE[i].outerHTML = repE[i].outerHTML;
  188. }
  189. }
  190. } catch (e) {
  191. console.log(e);
  192. }
  193. }
  194. } catch (e) {
  195. console.log(e);
  196. }
  197. }
  198. });
  199. }
  200. },
  201. };
  202.  
  203.  
  204. function getElementByXpath(e, t, r) {
  205. r = r || document, t = t || r;
  206. try {
  207. return r.evaluate(e, t, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  208. } catch (t) {
  209. return void console.error("无效的xpath");
  210. }
  211. }
  212.  
  213.  
  214. function getAllElements(e, t, r, n, o) {
  215. let getAllElementsByXpath = function(e, t, r) {
  216. return r = r || document, t = t || r, r.evaluate(e, t, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  217. }
  218.  
  219. var i, s = [];
  220. if (!e) return s;
  221. if (r = r || document, n = n || window, o = o || void 0, t = t || r, "string" == typeof e) i = 0 === e.search(/^css;/i) ? function getAllElementsByCSS(e, t) {
  222. return (t || document).querySelectorAll(e);
  223. }(e.slice(4), t) : getAllElementsByXpath(e, t, r); else {
  224. if (!(i = e(r, n, o))) return s;
  225. if (i.nodeType) return s[0] = i, s;
  226. }
  227. return function makeArray(e) {
  228. var t, r, n, o = [];
  229. if (e.pop) {
  230. for (t = 0, r = e.length; t < r; t++) (n = e[t]) && (n.nodeType ? o.push(n) : o = o.concat(makeArray(n)));
  231. return a()(o);
  232. }
  233. if (e.item) {
  234. for (t = e.length; t;) o[--t] = e[t];
  235. return o;
  236. }
  237. if (e.iterateNext) {
  238. for (t = e.snapshotLength; t;) o[--t] = e.snapshotItem(t);
  239. return o;
  240. }
  241. }(i);
  242. }
  243. })();