自动无缝翻页

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

当前为 2021-01-10 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 自动无缝翻页
  3. // @version 1.1.1
  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://github.com/favicon.ico
  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: 1300
  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: 1300
  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. let scrollDelta = curSite.pager.scrollDelta;
  92. if (document.documentElement.scrollHeight <= document.documentElement.clientHeight + scrollTop + scrollDelta) {
  93. ShowPager.loadMorePage();
  94. }
  95. }
  96. });
  97. }
  98. }
  99.  
  100.  
  101. // 滚动条事件
  102. function windowScroll(fn1) {
  103. var beforeScrollTop = document.documentElement.scrollTop,
  104. fn = fn1 || function () {};
  105. setTimeout(function () { // 延时执行,避免刚载入到页面就触发翻页事件
  106. window.addEventListener("scroll", function (e) {
  107. var afterScrollTop = document.documentElement.scrollTop,
  108. delta = afterScrollTop - beforeScrollTop;
  109. if (delta == 0) return false;
  110. fn(delta > 0 ? "down" : "up", e);
  111. beforeScrollTop = afterScrollTop;
  112. }, false);
  113. }, 1000)
  114. }
  115.  
  116.  
  117. var ShowPager = { // 修改自 https://greasyfork.org/scripts/14178
  118. getFullHref: function (e) {
  119. if(e == null) return '';
  120. "string" != typeof e && (e = e.getAttribute("href"));
  121. var t = this.getFullHref.a;
  122. return t || (this.getFullHref.a = t = document.createElement("a")), t.href = e, t.href;
  123. },
  124. createDocumentByString: function (e) {
  125. if (e) {
  126. if ("HTML" !== document.documentElement.nodeName) return (new DOMParser).parseFromString(e, "application/xhtml+xml");
  127. var t;
  128. try {
  129. t = (new DOMParser).parseFromString(e, "text/html");
  130. } catch (e) {
  131. }
  132. if (t) return t;
  133. if (document.implementation.createHTMLDocument) t = document.implementation.createHTMLDocument("ADocument"); else try {
  134. (t = document.cloneNode(!1)).appendChild(t.importNode(document.documentElement, !1)),
  135. t.documentElement.appendChild(t.createElement("head")), t.documentElement.appendChild(t.createElement("body"));
  136. } catch (e) {
  137. }
  138. if (t) {
  139. var r = document.createRange();
  140. r.selectNodeContents(document.body);
  141. var n = r.createContextualFragment(e);
  142. t.body.appendChild(n);
  143. for (var a, o = {
  144. TITLE: !0,
  145. META: !0,
  146. LINK: !0,
  147. STYLE: !0,
  148. BASE: !0
  149. }, i = t.body, s = i.childNodes, c = s.length - 1; c >= 0; c--) o[(a = s[c]).nodeName] && i.removeChild(a);
  150. return t;
  151. }
  152. } else console.error("没有找到要转成DOM的字符串");
  153. },
  154. loadMorePage: function () {
  155. if (curSite.pager) {
  156. let curPageEle = getElementByXpath(curSite.pager.nextLink);
  157. var url = this.getFullHref(curPageEle);
  158. //console.log(`${url} ${curPageEle} ${curSite.pageUrl}`);
  159. if(url === '') return;
  160. if(curSite.pageUrl === url) return;// 不会重复加载相同的页面
  161. curSite.pageUrl = url;
  162. // 读取下一页的数据
  163. curSite.pager.startFilter && curSite.pager.startFilter();
  164. GM_xmlhttpRequest({
  165. url: url,
  166. method: "GET",
  167. timeout: 5000,
  168. onload: function (response) {
  169. try {
  170. var newBody = ShowPager.createDocumentByString(response.responseText);
  171. let pageElems = getAllElements(curSite.pager.pageElement, newBody, newBody);
  172. let toElement = getAllElements(curSite.pager.HT_insert[0])[0];
  173. if (pageElems.length >= 0) {
  174. let addTo = "beforeend";
  175. if (curSite.pager.HT_insert[1] == 1) addTo = "beforebegin";
  176. // 插入新页面元素
  177. pageElems.forEach(function (one) {
  178. toElement.insertAdjacentElement(addTo, one);
  179. });
  180. // 替换待替换元素
  181. try {
  182. let oriE = getAllElements(curSite.pager.replaceE);
  183. let repE = getAllElements(curSite.pager.replaceE, newBody, newBody);
  184. if (oriE.length === repE.length) {
  185. for (var i = 0; i < oriE.length; i++) {
  186. oriE[i].outerHTML = repE[i].outerHTML;
  187. }
  188. }
  189. } catch (e) {
  190. console.log(e);
  191. }
  192. }
  193. } catch (e) {
  194. console.log(e);
  195. }
  196. }
  197. });
  198. }
  199. },
  200. };
  201.  
  202.  
  203. function getElementByXpath(e, t, r) {
  204. r = r || document, t = t || r;
  205. try {
  206. return r.evaluate(e, t, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  207. } catch (t) {
  208. return void console.error("无效的xpath");
  209. }
  210. }
  211.  
  212.  
  213. function getAllElements(e, t, r, n, o) {
  214. let getAllElementsByXpath = function(e, t, r) {
  215. return r = r || document, t = t || r, r.evaluate(e, t, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  216. }
  217.  
  218. var i, s = [];
  219. if (!e) return s;
  220. 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) {
  221. return (t || document).querySelectorAll(e);
  222. }(e.slice(4), t) : getAllElementsByXpath(e, t, r); else {
  223. if (!(i = e(r, n, o))) return s;
  224. if (i.nodeType) return s[0] = i, s;
  225. }
  226. return function makeArray(e) {
  227. var t, r, n, o = [];
  228. if (e.pop) {
  229. for (t = 0, r = e.length; t < r; t++) (n = e[t]) && (n.nodeType ? o.push(n) : o = o.concat(makeArray(n)));
  230. return a()(o);
  231. }
  232. if (e.item) {
  233. for (t = e.length; t;) o[--t] = e[t];
  234. return o;
  235. }
  236. if (e.iterateNext) {
  237. for (t = e.snapshotLength; t;) o[--t] = e.snapshotItem(t);
  238. return o;
  239. }
  240. }(i);
  241. }
  242. })();