Advertisement
axutongxue

QQ空间下载神器

May 7th, 2024
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.01 KB | None | 0 0
  1. // ==UserScript==
  2. // @name QQ空间相册下载神器
  3. // @name:zh [雪星实验室] QQ空间相册下载神器
  4. // @namespace https://userscript.snomiao.com/
  5. // @version 0.4.0
  6. // @description 批量下载小姐姐空间高清大图照片佳选插件~自动命名快速汲取dalao灵感~(bug反馈联系 snomiao@gmail.com ) 注:使用 chrome 的用户也可以考虑 QQ空间导出助手 插件
  7. // @author snomiao@gmail.com
  8. // @match *://user.qzone.qq.com/*
  9. // @match *://*.photo.store.qq.com/*
  10. // @match *://*.qpic.cn/*
  11. // @grant none
  12. // ==/UserScript==
  13. //
  14. // 注:使用 chrome 用户也可以考虑 QQ空间导出助手
  15. // https://chrome.google.com/webstore/detail/qq%E7%A9%BA%E9%97%B4%E5%AF%BC%E5%87%BA%E5%8A%A9%E6%89%8B/aofadimegphfgllgjblddapiaojbglhf
  16. //
  17. // 更新:(20210228) 0.4.0 修复史前照片下载
  18. // 更新:(20200518) 0.3.0 还是弹吧……(因为 IFRAME 没法监控状态可能会漏照片、用 xhr 和 fetch 会有跨域问题)
  19. // 更新:(20200501) 0.2.0 改进下载逻辑,不再弹出窗口
  20. //
  21. (() => {
  22. var 下载 = (url, filename = '') => {
  23. var a = document.createElement('a');
  24. a.style.display = 'none';
  25. a.href = url;
  26. a.download = filename;
  27. document.body.appendChild(a);
  28. a.click();
  29. a.remove();
  30. };
  31. var 响应被下载 = () => {
  32. var m = decodeURI(location.hash).match(/(?<=#下载-).*/);
  33. if (!m) return null;
  34. var filename = m[0];
  35. 下载(location.href, filename);
  36. (opener || parent).postMessage(
  37. '下载完成-' + location.href,
  38. 'https://user.qzone.qq.com'
  39. );
  40. window.close();
  41. };
  42. var 智能下载 = (url, filename = '') => {
  43. var 当页域名 = location.hostname;
  44. var 同源 = !!url.match(':/' + 当页域名 + '/');
  45. if (同源) return 下载(url, filename);
  46. if ('打开新页面') {
  47. // 或打开新页面
  48. var src = url + '#下载-' + encodeURI(filename);
  49. window.open(src, '_BLANK');
  50. return;
  51. }
  52. if ('使用IFRAME下载') {
  53. // 否则使用 iframe // iframe会漏照片……闲了再调试好了。。
  54. window.addEventListener(
  55. 'message',
  56. (e) => {
  57. var m = e.data && e.data.match(/(?<=下载完成-)(.*)/);
  58. if (!m) return;
  59. let url = m[0];
  60. // console.debug("删除iframe",e.origin, url);
  61. // e.origin ignore
  62. [...document.querySelectorAll('iframe')]
  63. .filter((e) => e.src == url)
  64. .forEach((e) => {
  65. // console.debug("删除了iframe",e.src, e);
  66. e.remove();
  67. });
  68. },
  69. false
  70. );
  71. document.body.appendChild(
  72. 新元素('<iframe style="visibility: hidden"></iframe>', {
  73. src: url + '#下载-' + encodeURI(filename),
  74. })
  75. );
  76. }
  77. };
  78. /* 一些常见源地址类型
  79. photogz.photo.store.qq.com
  80. http://b${数字}.photo.store.qq.com/psu // 比较早期的
  81. */
  82. var 高清地址を取 = (src) => {
  83. if (src.match(/\/\/b\d+\.photo\.store\.qq\.com\//)) {
  84. return src
  85. .replace('http:', 'https:')
  86. .replace(/\/\/.*?\//, '//r.photo.store.qq.com/')
  87. .replace(/null&.*$/, '')
  88. .replace(/\/(?:m|b)(\/|$)/, '/b$1') //高清(一些早期照片没有原图)
  89. .replace(/&(?:w|h)=\d+/, '');
  90. } else {
  91. return src
  92. .replace('http:', 'https:')
  93. .replace(/\/\/.*?\//, '//r.photo.store.qq.com/')
  94. .replace(/null&.*$/, '')
  95. .replace(/\/(?:m|b)(\/|$)/, '/r$1') //原图
  96. .replace(/&(?:w|h)=\d+/, '');
  97. }
  98. };
  99.  
  100. var 试取内容 = (e) => e?.textContent?.trim() || '';
  101. var 照片列を取 = () => {
  102. var 相册名 = 试取内容(document.querySelector('.j-pl-albuminfo-title'));
  103. return [...document.querySelectorAll('.j-pl-photoitem,.j-box-img')].map(
  104. (e, i) => ({
  105. src: e.querySelector('.j-pl-photoitem-img,.j-img').src,
  106. url: 高清地址を取(
  107. e.querySelector('.j-pl-photoitem-img,.j-img').src
  108. ),
  109. filename:
  110. (
  111. 相册名 +
  112. '-' +
  113. // (1 + i) + '-' +
  114. 试取内容(
  115. e.querySelector('.j-pl-photoitem-title,span[title]')
  116. ) +
  117. '-' +
  118. 试取内容(
  119. e.querySelector('.j-pl-photoitem-desc,j-photo-desc')
  120. )
  121. )
  122. .replace(/\/|\?|\*|\:|\||\\|\<|\>|\r|\n/, '_')
  123. .substr(0, 50) + '.jpg',
  124. })
  125. );
  126. };
  127. var 下载当页 = (globalThis.下载当页 = () => {
  128. const 试取列 = 照片列を取();
  129. const 列有效 = 试取列.every(({ src }) => src);
  130. if (列有效)
  131. return 照片列を取().forEach(({ url, filename }) =>
  132. 智能下载(url, filename)
  133. );
  134. // 自动滚动重试
  135. window.parent.scrollBy(0, window.innerHeight);
  136. window.scrollBy(0, window.innerHeight);
  137. setTimeout(下载当页, 200);
  138. });
  139. // UI
  140. var 新元素 = (innerHTML, attributes = {}) => {
  141. var e = document.createElement('div');
  142. e.innerHTML = innerHTML;
  143. return Object.assign(e.children[0], attributes);
  144. };
  145. var 生成下载界面 = () => {
  146. // “更多”按钮前插入一个按钮
  147. var 下载按钮 = 新元素('<div></div>', {
  148. className: 'photo-op-item photos-download',
  149. innerHTML:
  150. '<a class="c-tx2 bg3 bor gb-btn-nor" href="javascript:globalThis.下载当页()">下载当页</a>',
  151. title: '请滚动到底以确保当前页面所有照片都已加载',
  152. //onclick: 下载当页,
  153. });
  154. [
  155. ...document.querySelectorAll('.photo-op-item.photos-download'),
  156. ].forEach((e) => e.remove());
  157. var 更多按钮 = document.querySelector('.photo-op-item.j-pl-moreop');
  158. 更多按钮 && 更多按钮.parentNode.insertBefore(下载按钮, 更多按钮);
  159. };
  160.  
  161. // 被下载
  162. if (
  163. location.host.match(/.*\.photo\.store\.qq\.com/) ||
  164. location.host.match(/.*\.qpic\.cn/)
  165. )
  166. 响应被下载();
  167.  
  168. // 相册页面
  169. if (location.hostname == 'user.qzone.qq.com')
  170. window.addEventListener('load', 生成下载界面, false), 生成下载界面();
  171. })();
  172.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement