Forza图库图片批量下载

批量下载Forza玩家图库的图片

目前為 2018-12-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Forza图库图片批量下载
  3. // @namespace https://space.bilibili.com/68391#!/
  4. // @version 0.1
  5. // @description 批量下载Forza玩家图库的图片
  6. // @author 剧情帝
  7. // @match https://www.forzamotorsport.net/*/gallery/*
  8. // @grant GM_registerMenuCommand
  9. // @grant GM_download
  10. // @grant GM_addStyle
  11. // @grant GM_notification
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. let $photoArr, $photos, $selectModeBtn, $selectAllBtn, $downloadBtn, $resetBtn;
  18. let selectMode = false, downloading = false;
  19. let total_selected = 0;
  20. GM_registerMenuCommand('选择并下载图片', InitSelect);
  21.  
  22. function InitSelect(){
  23. $photos = $("#photos").addClass('select_mode');
  24. $photoArr = $(".photo", $photos);
  25. if($photoArr.length === 0){
  26. alert('请在图片列表加载完毕后重试');
  27. return;
  28. }
  29.  
  30. selectMode = true;
  31.  
  32. GM_addStyle((`
  33. .photo .media_element {
  34. display: flex;
  35. }
  36. .photos.select_mode .photo .media_element a {
  37. /*pointer-events: none;*/
  38. }
  39. .photo .image {
  40. position: relative;
  41. }
  42. .photo .selectbox{
  43. display: none;
  44. }
  45. .photos.select_mode .photo .selectbox {
  46. display: flex;
  47. position: absolute;
  48. top: 0;
  49. left: 0;
  50. width: 100%;
  51. height: 100%;
  52. text-align: center;
  53. font-size: 20px;
  54. justify-content: center;
  55. align-items: center;
  56. background-color: rgba(0, 0, 0, 0.3);
  57. color: #fff;
  58. }
  59. .photos.select_mode .photo .selectbox:hover{
  60. background-color: unset;
  61. font-size: 0;
  62. }
  63. .photos.select_mode .photo .selectbox.selected{
  64. font-size: 0;
  65. background-color: unset;
  66. border: 5px solid #00a1d6;
  67. }
  68. .photos.select_mode .photo .selectbox.downloading{
  69. font-size: 20px;
  70. background-color: rgba(0, 0, 0, 0.3);
  71. border: 5px solid #ff0;
  72. }
  73. .photos.select_mode .photo .selectbox.downloaded{
  74. font-size: 20px;
  75. background-color: rgba(0, 0, 0, 0.3);
  76. border: 5px solid #0f0;
  77. }
  78. .photos.select_mode .photo .selectbox.failed{
  79. font-size: 20px;
  80. background-color: rgba(0, 0, 0, 0.3);
  81. border: 5px solid #f00;
  82. }
  83. .tool_box{
  84. position:fixed;
  85. right: 10px;
  86. top:40%;
  87. background-color: #cf4335;
  88. padding: 10px;
  89. border-radius: 3px;
  90. max-width: 100px;
  91. }
  92. .tool_box #mode, .tool_box label{
  93. vertical-align: middle;
  94. }
  95. .tool_box input[type="button"]{
  96. display: block;
  97. width: 70px;
  98. margin: 10px auto auto auto;
  99. }
  100. .tool_box p{
  101. width: 100%;
  102. text-align: center;
  103. margin-top: 10px;
  104. }
  105. `));
  106.  
  107. let $toolBox = $(`<div class="tool_box">
  108. <input id="mode" type="checkbox" checked="checked"><label for="mode">选择模式</label>
  109. <input id="select_all" type="button" value="选择全部">
  110. <input id="download" type="button" value="下载">
  111. <input id="reset" type="button" value="重置" disabled="disabled">
  112. <p>在选择模式下,直接左键点击图片来选择,中键单击可以在新标签页查看图像</p>
  113. </div>
  114. `);
  115. $selectModeBtn = $("#mode", $toolBox);
  116. $selectAllBtn = $("#select_all", $toolBox);
  117. $downloadBtn = $("#download", $toolBox);
  118. $resetBtn = $("#reset", $toolBox);
  119. $("body").append($toolBox);
  120.  
  121. $photoArr.each((index, photo)=>{
  122. let $photo = $(photo);
  123. let $select = $('<div class="selectbox">未选择</div>');
  124. $("a", $photo).click(()=>{
  125. return !selectMode; //图片选择模式下阻止点击图片的默认行为
  126. });
  127. $select.click( SelectPic);
  128. $('.image', $photo).append($select);
  129. });
  130.  
  131. //“选择模式”按钮功能
  132. $selectModeBtn.change(()=>{
  133. selectMode = !selectMode;
  134. if(selectMode){
  135. $photos.addClass('select_mode');
  136. $selectAllBtn.prop('disabled', false);
  137. $downloadBtn.prop('disabled', false);
  138. }
  139. else{
  140. $photos.removeClass('select_mode');
  141. $selectAllBtn.prop('disabled', true);
  142. $downloadBtn.prop('disabled', true);
  143. }
  144. });
  145.  
  146. //全选按钮功能
  147. $selectAllBtn.click(()=>{
  148. if($selectAllBtn.val() === '选择全部'){
  149. $(".selectbox", $photoArr).addClass('selected');
  150. total_selected = $photoArr.length;
  151. }
  152. else if($selectAllBtn.val() === '取消全选'){
  153. $(".selectbox", $photoArr).removeClass('selected');
  154. total_selected = 0;
  155. }
  156. AlterSelectAllButton();
  157. });
  158.  
  159. //下载按钮功能
  160. $downloadBtn.click(DownloadImgs);
  161.  
  162. //重置按钮功能
  163. $resetBtn.click(()=>{
  164. downloading = false;
  165. $selectModeBtn.prop('disabled', false);
  166. $selectAllBtn.prop('disabled', false).val('选择全部');
  167. $downloadBtn.prop('disabled', false);
  168. $resetBtn.prop('disabled', true);
  169. total_selected = 0;
  170. $(".selectbox.selected", $photos).removeClass('selected downloading downloaded failed').text('未选择');
  171. });
  172. }
  173.  
  174. function SelectPic() {
  175. if(downloading)
  176. return;
  177.  
  178. let $selectBox = $(this);
  179. // $selectBox.toggleClass('selected');
  180. if(!$selectBox.hasClass('selected')){
  181. $selectBox.addClass('selected');
  182. total_selected++;
  183. }
  184. else{
  185. $selectBox.removeClass('selected');
  186. total_selected--;
  187. }
  188. AlterSelectAllButton();
  189. }
  190.  
  191. function AlterSelectAllButton() {
  192. $selectAllBtn.val( (total_selected === $photoArr.length) ? '取消全选' : '选择全部' );
  193. }
  194.  
  195. function DownloadImgs() {
  196. if(total_selected === 0){
  197. alert('您没有选中任何图片!');
  198. return;
  199. }
  200.  
  201. let choose = confirm(`注意:请不要在浏览器下载设置中选中 “下载前询问每个文件的保存位置” !!!否则会弹出多个对话框。\n\n已选中 ${total_selected} 张图片,点击“是”开始下载`);
  202. if(choose === false)
  203. return;
  204.  
  205. $selectModeBtn.prop('disabled', true);
  206. $selectAllBtn.prop('disabled', true);
  207. $downloadBtn.prop('disabled', true);
  208. downloading = true;
  209.  
  210. let index = 0;
  211. let $selectedBoxs = $(".selectbox.selected", $photos);
  212. let total_downloaded = 0, total_failed = 0;
  213. DownloadImg( index);
  214.  
  215. //递归下载
  216. function DownloadImg( index) {
  217. if(index >= total_selected){
  218. //下载全部结束
  219. GM_notification( (total_downloaded === total_selected) ? '所有图片下载成功!' : `下载结束,成功下载${total_downloaded}张图片,${total_failed}张失败` );
  220. console.log( (total_downloaded === total_selected) ? '所有图片下载成功!' : `下载结束,成功下载${total_downloaded}张图片,${total_failed}张失败` );
  221. $resetBtn.prop('disabled', false);
  222. return;
  223. }
  224.  
  225. let $selectedBox = $selectedBoxs.eq(index);
  226. let $img = $selectedBox.prev('img');
  227. let imgSrc = $img.attr('src').replace('/thumbnail', '');
  228. let imgName = `${$img.attr('title')} ${imgSrc.split('/').pop()}.jpg`;
  229. console.log(`第${index+1}张图片${imgName}开始下载`);
  230. $selectedBox.addClass('downloading').text('正在下载');
  231. GM_download({
  232. url: imgSrc,
  233. name: imgName,
  234. onload: () => {
  235. console.info(`第${index+1}张图片${imgName}下载成功`);
  236. $selectedBox.removeClass('downloading').addClass('downloaded').text('下载完成');
  237. total_downloaded++;
  238. setTimeout(() => {
  239. DownloadImg(index + 1);
  240. }, 3000);
  241. },
  242. onerror: () => {
  243. console.error(`第${index+1}张图片${imgName}下载失败`);
  244. $selectedBox.removeClass('downloading').addClass('failed').text('下载失败');
  245. total_failed++;
  246. setTimeout(() => {
  247. DownloadImg(index + 1);
  248. }, 3000);
  249. },
  250. ontimeout: () => {
  251. console.error(`第${index+1}张图片${imgName}下载超时`);
  252. $selectedBox.removeClass('downloading').addClass('failed').text('下载超时');
  253. total_failed++;
  254. setTimeout(() => {
  255. DownloadImg(index + 1);
  256. }, 3000);
  257. }
  258. });
  259. }
  260. }
  261.  
  262. })();