├── .eslintrc.js ├── LICENSE ├── README-EN.md ├── README.md ├── XZPixivDownloader.user.js └── log.md /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": false, 5 | "es6": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "sourceType": "module", 10 | "ecmaVersion": 8 11 | }, 12 | "rules": { 13 | "indent": [0, "tab"], 14 | "linebreak-style": ["error", "windows"], 15 | "quotes": [0, "single"], 16 | "semi": [2, "always"], 17 | "no-console": "off" 18 | }, 19 | "globals": { 20 | "GM_info": true, 21 | "unsafeWindow": true, 22 | "GM_xmlhttpRequest": true, 23 | "GM_download": true, 24 | "browser": true, 25 | "zip": true, 26 | "GIF": true, 27 | "Viewer": true 28 | } 29 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README-EN.md: -------------------------------------------------------------------------------- 1 | ## Note: 2 | 3 | **This version (script version) will only perform basic maintenance in the future and will not add new features. Please migrate to the Chrome extension as soon as possible.** 4 | 5 | Install Chrome extension:[Offline installation tutorial](https://github.com/xuejianxianzun/PixivBatchDownloader/wiki/2.-%E5%AE%89%E8%A3%85#%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85) 6 | 7 | [Chrome extension Github page](https://github.com/xuejianxianzun/PixivBatchDownloader) 8 | 9 | [Chrome extension wiki](https://github.com/xuejianxianzun/PixivBatchDownloader/wiki) 10 | 11 | ** If you have an extended version installed, you will need to disable this script version. ** Do not let both versions run at the same time. 12 | 13 | # Introduction: 14 | 15 | This is a Pixiv image downloader written in JavaScript that supports many page types and filters. 16 | 17 | Some additional features have been added, such as removing ads, quick collections, Add tag to unclassified work, and viewing pictures. 18 | 19 | It is essentially a user script (UserScript) that must be installed using the User Script Manager. 20 | 21 | ![仙尊 pixiv 下载器 英文截图](https://wx4.sinaimg.cn/large/640defebly1fzm7xsh5vdj20kw0iz0v6.jpg) 22 | 23 | ### Recommended Use: 24 | 25 | Browser: **Chrome** [(download Chrome browser)](https://www.google.com/chrome/) 26 | 27 | User Script Manager: **Tampermonkey** [(view in Chrome webstore)](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo) 28 | 29 | - Please turn off "Ask where to save each file before downloading" in browser settings. 30 | 31 | # Install: 32 | 33 | You can install it at greasyfork.org: 34 | 35 | [https://greasyfork.org/zh-CN/scripts/24252](https://greasyfork.org/zh-CN/scripts/24252) 36 | 37 | The downloaded file will be saved in your browser's download directory. 38 | 39 | # Browser extension: 40 | 41 | This tool has a browser extension. If you want to use a browser extension, you can uninstall the scripted version and install the browser extension. 42 | 43 | [GitHub](https://github.com/xuejianxianzun/PixivBatchDownloader/wiki/2.-%E5%AE%89%E8%A3%85#%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85) 44 | 45 | # Supported languages: 46 | 47 | Simplified Chinese 48 | 49 | Traditional Chinese (thanks [道满](https://zhtw.me/) for translation) 50 | 51 | English (machine translation, also used under Korean settings) 52 | 53 | 日本語 (machine translation) 54 | 55 | You can also optimize the translation, thank you very much :) 56 | 57 | # Tips: 58 | 59 | - Browser's resource limits 60 | 61 | When you download picture, this page uses more memory and cpu resources. If you switch to another page and the download page is not activated, Browser will limit the resource usage of the download page, resulting in slow download. 62 | 63 | How to solve: Pull out the downloaded tabs individually and become a separate window. This page is the only one in the new window and it is always active. Downloads are not affected, we can use other pages too. 64 | 65 | - How to view the animation ( ugoira image ): 66 | 67 | The animated picture is suffixed with ugoira. Please install HoneyView software. Open the ugoira file with HoneyView to see the animation effect. 68 | 69 | Now you can download the gif image directly for a single animation. 70 | 71 | # Available pages and test URL: 72 | 73 | - [Index page](https://www.pixiv.net/) 74 | 75 | - [ALL works page](https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62751951) 76 | 77 | - [ALL works list page](https://www.pixiv.net/member_illust.php?id=544479) 78 | 79 | - [ALL tag list page](https://www.pixiv.net/member_illust.php?id=544479&tag=%E6%9D%B1%E6%96%B9) 80 | 81 | - [ALL bookmarks page](https://www.pixiv.net/bookmark.php?id=544479) 82 | 83 | - [ALL tag search page](https://www.pixiv.net/search.php?s_mode=s_tag&word=saber) 84 | 85 | - [Ranking page](https://www.pixiv.net/ranking.php) 86 | 87 | - [Area ranking page](https://www.pixiv.net/ranking_area.php?type=state&no=0) 88 | 89 | - [Similar works page](https://www.pixiv.net/bookmark_add.php?id=63148723) 90 | 91 | - [Discovery page](https://www.pixiv.net/discovery) 92 | 93 | - [New work: everyone](https://www.pixiv.net/new_illust.php) 94 | 95 | - [New work: following](https://www.pixiv.net/bookmark_new_illust.php) 96 | 97 | - [Illustration, comics, cosplay page on pixivision](https://www.pixivision.net/zh/a/3190) 98 | 99 | ## Library used: 100 | 101 | [Viewer.js](https://github.com/fengyuanchen/viewerjs) 102 | 103 | [zip.js](https://github.com/gildas-lormeau/zip.js) 104 | 105 | [gif.js](https://github.com/jnordberg/gif.js) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [View English introduction](https://github.com/xuejianxianzun/XZPixivDownloader/blob/master/README-EN.md) 2 | 3 | ## 注意: 4 | 5 | **这个版本(脚本版)未来只会进行基础的维护,不再添加新功能。请用户尽快迁移到 Chrome 扩展版本。** 6 | 7 | 安装 Chrome 扩展版:[离线安装](https://github.com/xuejianxianzun/PixivBatchDownloader/wiki/2.-%E5%AE%89%E8%A3%85#%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85) 8 | 9 | [Chrome 扩展版 Github 页面](https://github.com/xuejianxianzun/PixivBatchDownloader) 10 | 11 | [Chrome 扩展版的 wiki](https://github.com/xuejianxianzun/PixivBatchDownloader/wiki) 12 | 13 | **如果你安装了扩展版,需要禁用这个脚本版。** 不要让两个版本同时运行。 14 | 15 | # 简介: 16 | 17 | 这是一个使用 JavaScript 编写的 Pixiv 图片下载器,支持多种页面类型和筛选条件。 18 | 19 | 现在也增加了一些辅助功能,如去除广告、快速收藏、看图模式、给未分类作品添加 tag 等。 20 | 21 | 它实质上是一个用户脚本(UserScript),必须使用用户脚本管理器来安装。 22 | 23 | ![仙尊 pixiv 下载器 中文截图](https://wx4.sinaimg.cn/large/640defebly1fzm7xsi3dfj20kl0jftay.jpg) 24 | 25 | ## 推荐环境: 26 | 27 | 浏览器:**Chrome** [(下载Chrome浏览器,此链接需要翻墙)](https://www.google.com/chrome/) 28 | 29 | 用户脚本管理器:**Tampermonkey** [(在Chrome网上商店查看,此链接需要翻墙)](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo) 30 | 31 | - 请关闭浏览器设置中的“下载前询问每个文件的保存位置”选项,以免在下载时出现弹窗。 32 | 33 | - 推荐使用 Chrome。如果你使用其他浏览器,可能会出现内存占用过高、或者下载后无法保存文件的问题(常见于各种国产套壳浏览器)。 34 | 35 | # 安装: 36 | 37 | 你可以在greasyfork.org上安装它: 38 | 39 | [https://greasyfork.org/zh-CN/scripts/24252](https://greasyfork.org/zh-CN/scripts/24252) 40 | 41 | 下载的文件会保存在浏览器的下载目录里。 42 | 43 | # 浏览器扩展: 44 | 45 | 本工具有浏览器扩展版本。如果你想使用浏览器扩展,可以卸载脚本版,然后安装浏览器扩展。 46 | 47 | [GitHub](https://github.com/xuejianxianzun/PixivBatchDownloader/wiki/2.-%E5%AE%89%E8%A3%85#%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85) 48 | 49 | ## 支持的语言: 50 | 51 | 简体中文 52 | 53 | 繁體中文(感谢网友 [道滿](https://zhtw.me/) 进行翻译) 54 | 55 | English (机翻,韩语设置下也使用英语文本) 56 | 57 | 日本語 (机翻) 58 | 59 | 欢迎您对翻译做出改进,谢谢~ 60 | 61 | ## 提示: 62 | 63 | - 浏览器的资源限制问题 64 | 65 | 下载p站图片时,该页面会占用较多内存和cpu资源。如果切换到了其他页面,导致下载页面未激活,那么浏览器就会限制下载页面的资源使用,导致下载缓慢。 66 | 67 | 解决办法:把下载的标签页单独拖出来,成为一个独立的窗口。新窗口里只有这一个页面,它始终是激活的。这样下载不受影响,我们也可以使用其他页面了。 68 | 69 | - 如何查看动图: 70 | 71 | 动画图片下载之后,后缀名是 ugoira,请安装看图软件 HoneyView,之后用 HoneyView 打开 ugoira 文件可以查看动图效果。(但是文件体积大了,HoneyView 播放的帧率会变慢) 72 | 73 | 现在对单个动图可以直接下载 gif 图片。 74 | 75 | - 如有问题或建议,欢迎加 QQ 群 499873152 进行交流。 76 | 77 | ## 捐助: 78 | 79 | 如果您感觉本脚本帮到了您,您可以对我进行捐赠,不胜感激 (*╹▽╹*) 80 | 81 | (可通过微信和支付宝扫码转账) 82 | 83 | ![支付宝](https://i.loli.net/2019/04/04/5ca5627614396.png) ![微信](https://i.loli.net/2019/04/04/5ca5627630bb4.png) 84 | 85 | ## 可以使用的页面类型以及测试网址: 86 | 87 | 0 [首页](https://www.pixiv.net/) 88 | 89 | 1 [作品页面](https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62751951) 90 | 91 | 2 [作品列表页](https://www.pixiv.net/member_illust.php?id=544479) 92 | 93 | 2 [tag列表页](https://www.pixiv.net/member_illust.php?id=544479&tag=%E6%9D%B1%E6%96%B9) 94 | 95 | 2 [收藏页面](https://www.pixiv.net/bookmark.php) 96 | 97 | 5 [tag搜索页](https://www.pixiv.net/search.php?s_mode=s_tag&word=saber) 98 | 99 | 6 [地区排行榜](https://www.pixiv.net/ranking_area.php?type=state&no=0) 此板块已不再出现,只能通过网址进入 100 | 101 | 7 [排行榜](https://www.pixiv.net/ranking.php) 102 | 103 | 8 [pixivision上的插画、漫画、cosplay页面](https://www.pixivision.net/zh/a/3190) 104 | 105 | 9 [相似作品](https://www.pixiv.net/bookmark_add.php?id=63148723) 此板块已不再出现,只能通过网址进入 106 | 107 | 10 [大家的新作品](https://www.pixiv.net/new_illust.php) 108 | 109 | 10 [关注的新作品](https://www.pixiv.net/bookmark_new_illust.php) 110 | 111 | 11 [发现](https://www.pixiv.net/discovery) 112 | 113 | ## 使用的库: 114 | 115 | [Viewer.js](https://github.com/fengyuanchen/viewerjs) 116 | 117 | [zip.js](https://github.com/gildas-lormeau/zip.js) 118 | 119 | [gif.js](https://github.com/jnordberg/gif.js) 120 | 121 | ## 友情链接: 122 | 123 | [PixivUserBatchDownload](https://github.com/Mapaler/PixivUserBatchDownload/) 124 | 125 | 这是另一个工具——“P站画师个人作品批量下载工具”,简称PUBD。专注按画师下载作品,适合动手能力强的用户使用。 126 | 127 | - 专做按作者下载,适合有专情画师的粉丝。 128 | 129 | - 配合Aria2下载,可发送到本地或远端路由器。 130 | 131 | - 可使用程序语言高度自定义保存文件夹、重命名。 132 | 133 | ## Chrome 72 的问题 134 | 135 | Chrome 72 因为增加了一些限制,导致 Tampermonkey 一些功能失效,导致本工具下载出现异常。 136 | 137 | 解决办法: 138 | 139 | - 升级 Tampermonkey 到最新版本(在 Chrome 上,需要 Tampermonkey 4.8 或更高版本) 140 | 141 | - 此外,你也可以切换到本工具的浏览器扩展版,扩展版没有出现这个问题。 -------------------------------------------------------------------------------- /XZPixivDownloader.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name 仙尊 Pixiv 图片批量下载器 3 | // @name:ja XZ Pixiv Batch Downloader 4 | // @name:en XZ Pixiv Batch Downloader 5 | // @namespace http://saber.love/?p=3102 6 | // @version 6.9.0 7 | // @description 批量下载画师、书签、排行榜、搜索页等作品原图;查看热门作品;建立文件夹;转换动图为 gif;屏蔽广告;快速收藏作品(自动添加tag);不跳转直接查看多 p 作品;按收藏数快速搜索 tag;给未分类作品添加 tag。支持简繁中文、日语、英语。Github: https://github.com/xuejianxianzun/XZPixivDownloader 8 | // @description:ja アーティスト、ブックマーク、リーダーボード、検索ページなどのアーティストのオリジナル作品を一括ダウンロードする、人気の作品を表示する、フォルダを作成する、動画をgifに変換する、広告をすばやくブロックする、自動的にタグを追加する ;お気に入りの数でタグをすばやく検索し、分類されていない作品にタグを追加します。Github: https://github.com/xuejianxianzun/XZPixivDownloader 9 | // @description:en Batch download original works of artists such as artists, bookmarks, leaderboards, search pages, etc.; view popular works; create folders; convert moving images to gif; block ads; quickly collect works (automatically add tags); do not jump to view multiple p works ; Quickly search for tags by number of favorites; add tags to unclassified works. Github: https://github.com/xuejianxianzun/XZPixivDownloader 10 | // @author xuejianxianzun 雪见仙尊 11 | // @include *://www.pixiv.net/* 12 | // @include *://www.pixivision.net/* 13 | // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt 14 | // @icon https://www.pixiv.net/favicon.ico 15 | // @grant GM_xmlhttpRequest 16 | // @grant GM_download 17 | // @connect i.pximg.net 18 | // @connect i1.pixiv.net 19 | // @connect i2.pixiv.net 20 | // @connect i3.pixiv.net 21 | // @connect i4.pixiv.net 22 | // @connect i5.pixiv.net 23 | // @connect imgaz.pixiv.net 24 | // @run-at document-end 25 | // ==/UserScript== 26 | 27 | /* author: xuejianxianzun; 雪见仙尊 28 | * E-mail: xuejianxianzun@gmail.com 29 | * Github: https://github.com/xuejianxianzun/XZPixivDownloader 30 | * Website: https://pixiv.download/ 31 | * QQ群: 499873152 32 | */ 33 | 34 | 'use strict'; 35 | 36 | // 检测扩展版,使二者同时只运行一个 37 | if (sessionStorage.getItem('xz_pixiv_extension')) { 38 | throw 'extension ver is running'; 39 | } else { // 标注自己 40 | sessionStorage.setItem('xz_pixiv_userscript', '1'); 41 | } 42 | 43 | let quiet_download = true, // 是否快速下载。当可以下载时自动开始下载(无需点击下载按钮) 44 | download_XMPsidecar = false, //是否下载XML Sidecar文件 45 | download_thread_deauflt = 6, // 同时下载的线程数,可以通过设置 download_thread 修改 46 | multiple_down_number = 0, // 设置多图作品下载前几张图片。0为不限制,全部下载。改为1则只下载第一张。这是因为有时候多p作品会导致要下载的图片过多,此时可以设置只下载前几张,减少下载量 47 | display_cover = true, //是否显示tag搜索页里面的封面图片。如果tag搜索页的图片数量太多,那么加载封面图可能要很久,并且可能因为占用大量带宽导致抓取中断。这种情况下可以将此参数改为false,不加载封面图。 48 | fileName_length = 200, // 文件名的最大长度,超出将会截断。如果文件的保存路径过长可能会保存失败,此时可以把这个数值改小些。 49 | tagName_to_fileName = true, // 添加标记名称 50 | viewer_enable = true, // 是否启用看图模式 51 | xz_setting, // 保存的设置 52 | loc_url, // 页面的url 53 | page_type, // 页面类型 54 | old_page_type, // 上一个页面类型 55 | tag_mode, // page_type 2 里,是否带 tag 56 | works_type, // page_type 2 里的页面类型 57 | offset_number = 0, // 要去掉的作品数量 58 | once_request = 100, // 每次请求多少个数量 59 | type2_id_list = [], // 储存 page_type 2 的 id 列表 60 | img_info = [], // 储存图片信息,其中可能会有空值,如 undefined 和 '' 61 | illust_url_list = [], //储存作品列表url的数组 62 | imgList = [], //储存tag搜索页的所有作品 63 | ajax_for_illust_threads = 5, //抓取页面时的并发连接数 64 | ajax_for_illust_delay = 100, //抓取页面的并发请求每个间隔多少毫秒 65 | ajax_threads_finished = 0, //统计有几个并发线程完成所有请求。统计的是并发数(ajax_for_illust_threads)而非请求数 66 | test_suffix_finished = true, //检查图片后缀名正确性的函数是否执行完毕 67 | test_suffix_no = 0, //检查图片后缀名函数的计数 68 | now_tips = '', //输出顶部提示 69 | base_url, //列表页url规则 70 | startpage_no, //列表页开始抓取时的页码 71 | listPage_finished = 0, //记录一共抓取了多少列表页 72 | listPage_finished2 = 0, //记录tag搜索页本次任务已经抓取了多少页 73 | want_page, //要抓取几页 74 | quick = false, // 快速下载当前页面,这个只在作品页内直接下载时使用 75 | interrupt = false, //是否中断正在进行的任务,目前仅在tag搜索页使用 76 | allow_work = true, //当前是否允许展开工作(如果有未完成的任务则会变为false 77 | notNeed_tag = [], //要排除的tag的列表 78 | need_tag = [], //必须包含的tag的列表 79 | notdown_type = '', //设置不要下载的作品类型 80 | is_set_filterWH = false, //是否设置了筛选宽高 81 | filterWH = { 82 | and_or: '&', 83 | width: 0, 84 | height: 0 85 | }, //宽高条件 86 | is_set_filterBMK = false, // 是否设置了筛选收藏数 87 | filterBMK = 0, 88 | part_number, //保存不同排行榜的列表数量 89 | requset_number = 0, //要下载多少个作品 90 | max_num = 0, //最多允许获取多少数量 91 | list_is_new, // 列表页加载模式是否是新版 92 | tag_search_lv1_selector, // tag搜索页,储存作品信息的元素 93 | tag_search_list_wrap = '.x7wiBV0', // tag搜索页,储存作品列表的元素 94 | tag_search_list_selector, // tag搜索页,直接选择作品的选择器 95 | tag_search_multiple_selector = '._3b8AXEx', // 多图作品的选择器 96 | tag_search_gif_selector = '.AGgsUWZ', // 动图作品的选择器 97 | tag_search_new_html, // tag搜索页作品的html 98 | xz_multiple_html, // tag搜索页作品的html中的多图标识 99 | xz_gif_html, // tag搜索页作品的html中的动图标识 100 | safe_fileName_rule = new RegExp(/\\|\/|:|\?|"|<|'|>|\*|\||~|\u200b|\.$/g), // 安全的文件名 101 | safe_folder_rule = new RegExp(/\\|:|\?|"|<|'|>|\*|\||~|\u200b|\.$/g), // 文件夹名,允许斜线 / 102 | rightButton, // 右侧按钮 103 | centerWrap, // 中间设置面板 104 | center_btn_wrap, // 中间插入按钮的区域 105 | xz_blue = '#0ea8ef', 106 | xz_green = '#14ad27', 107 | xz_red = '#f33939', 108 | downloadBar_list, // 下载队列的dom元素 109 | download_thread, // 下载线程 110 | download_a, // 下载用的a标签 111 | download_started = false, // 下载是否已经开始 112 | downloaded = 0, // 已下载的文件 113 | download_stop = false, // 是否停止下载 114 | download_pause = false, // 是否暂停下载 115 | old_title = document.title, // 原始 title,需要加下载状态时使用 116 | title_timer, 117 | click_time = 0, // 点击下载按钮的时间戳 118 | time_delay = 0, // 延迟点击的时间 119 | time_interval = 400, // 为了不会漏下图,设置的两次点击之间的间隔时间。下载图片的速度越快,此处的值就需要越大。默认的400是比较大的,如果下载速度慢,可以尝试改成300/200。 120 | down_xiangguan = false, // 下载相关作品(作品页内的) 121 | viewerWarpper, // 图片列表的容器 122 | viewerUl, // 图片列表的 ul 元素 123 | myViewer, // 查看器 124 | quickBookmarkElement, // 快速收藏的元素 125 | download_gif_btn, // 下载 gif 的按钮 126 | gif_js_urls = ['https://cdn.jsdelivr.net/npm/@trigrou/zip-js@1.0.0/WebContent/zip.js', 'https://cdn.jsdelivr.net/npm/@trigrou/zip-js@1.0.0/WebContent/z-worker.js', 'https://cdn.jsdelivr.net/npm/@trigrou/zip-js@1.0.0/WebContent/inflate.js', 'https://cdn.jsdelivr.net/npm/gif.js@0.2.0/dist/gif.js', 'https://cdn.jsdelivr.net/npm/gif.js@0.2.0/dist/gif.worker.js'], 127 | convert_lib_loaded = false, // 动图组件加载情况 128 | convert_lib_urls = {}, // 动图组件 js 的 url, 129 | check_convert_timer, // 检查动图是否可以转换时,使用的的定时器 130 | gif_img_list, // 储存 gif 图片列表的元素 131 | zip_file = null, // 获取的 zip 文件 132 | file_number = undefined, // 动图压缩包里有多少个文件 133 | gif_src = '', // 动图源文件 url 134 | gif_mime_type = '', // 图片 mime type 135 | gif_delay, // 动图帧延迟 136 | XZForm, 137 | XZTipEl, 138 | styleE, 139 | page_info = {}, // 文件夹可以使用的命名信息 140 | p_user = '', 141 | option_area_show = true, 142 | del_work = false, // 是否处于删除作品状态 143 | only_down_bmk, 144 | ratio_type = '0', 145 | isFirefox = navigator.userAgent.includes('Firefox'), 146 | allowFolder = GM_info.downloadMode === 'browser' && !isFirefox, // 是否可以建立下载文件夹 147 | pause_start_dealy = 2500, // 点击暂停后,一定时间后才允许点击开始下载按钮 148 | can_start_time = 0; // 在此时间之后允许点击开始下载按钮 149 | 150 | // 多语言配置 151 | let lang_type; // 语言类型 152 | let user_lang = document.documentElement.lang; //获取语言选项 153 | switch (user_lang) { 154 | case 'zh': 155 | case 'zh-CN': 156 | case 'zh-Hans': 157 | lang_type = 0; // 设置为简体中文 158 | break; 159 | case 'ja': 160 | lang_type = 1; // 设置为日语 161 | break; 162 | case 'zh-Hant': 163 | case 'zh-tw': 164 | case 'zh-TW': 165 | lang_type = 3; // 设置为繁体中文 166 | break; 167 | default: 168 | lang_type = 2; // 设置为英语 169 | break; 170 | } 171 | 172 | // 日文和英文目前是机翻,欢迎对翻译进行完善 173 | let xz_lang = { // 储存语言配置。在属性名前面加上下划线,和文本内容做出区别。{}表示需要进行替换的部分 174 | '_过滤作品类型的按钮': [ 175 | '排除指定类型的作品', 176 | 'タイプでフィルタリングする', 177 | 'Filter by works type', 178 | '排除指定類型的作品' 179 | ], 180 | '_过滤作品类型的按钮_title': [ 181 | '在下载前,您可以设置想要排除的作品类型。', 182 | 'ダウンロードする前に、除外するタイプを設定することができます。', 183 | 'Before downloading, you can set the type you want to exclude.', 184 | '在下載前,您可以設定想要排除的作品類型' 185 | ], 186 | '_过滤作品类型的弹出框文字': [ 187 | '请输入数字来设置下载时要排除的作品类型。\n如需多选,将多个数字连写即可\n如果什么都不输入,那么将不排除任何作品\n1: 排除单图\n2: 排除多图\n3: 排除动图\n4: 排除已经收藏的作品', 188 | 'ダウンロード時に除外するタイプを設定する番号を入力してください。\nさまざまなオプションが必要な場合は、それを連続して入力することができます。\n1.単一の画像の作品を除外する\n2.複数の画像の作品を除外する\n3.うごイラの作品を除外する\n4: ブックマーク', 189 | 'Please enter a number to set the type of you want to excluded when downloading.\nIf you need multiple choice, you can enter continuously.\n1: one-images works\n2.multiple-images works\n3.animat works\n4.bookmarked works', 190 | '請輸入數字來設定下載時要排除的作品類型。\n如需多選,將多個數字連寫即可\n如果什麼都不輸入,那麼將不排除任何作品\n1: 排除單圖\n2: 排除多圖\n3: 排除動圖\n4: 排除已經收藏的作品' 191 | ], 192 | '_只下载已收藏': [ 193 | '只下载已收藏', 194 | 'ブックマークのみをダウンロードする', 195 | 'Download only bookmarked works', 196 | '只下載已收藏' 197 | ], 198 | '_只下载已收藏的提示': [ 199 | '只下载已经收藏的作品', 200 | '既に収集された作品のみをダウンロードする', 201 | 'Download only bookmarked works', 202 | '只下載已經收藏的作品' 203 | ], 204 | '_设置作品类型': [ 205 | '设置作品类型', 206 | 'ダウンロードする作品のタイプを設定する', 207 | 'Set the type of work', 208 | '設定作品類型' 209 | ], 210 | '_设置作品类型的提示_center': [ 211 | '下载哪些类型的作品', 212 | 'ダウンロードする作品の種類', 213 | 'Which types of works to download', 214 | '下載哪些類型的作品' 215 | ], 216 | '_多p下载前几张': [ 217 | '多图作品设置', 218 | 'マルチピクチャワーク設定', 219 | 'Multiple images work setting', 220 | '多圖作品設定' 221 | ], 222 | 223 | '_多p下载前几张提示': [ 224 | '如果数字大于 0,多图作品只会下载前几张图片。(按照设置的数量)', 225 | '数字が0より大きい場合、マルチピクチャは最初のいくつかのイメージのみをダウンロードします。 (設定数に応じて)', 226 | 'If the number is greater than 0, the multiple images work will only download the first few images. (according to the number of settings)', 227 | '如果數字大於 0,多圖作品只會下載前幾張圖片。(依照設定的數量)' 228 | ], 229 | '_排除tag的按钮文字': [ 230 | '设置作品不能包含的tag', 231 | '作品に含まれていないタグを設定する', 232 | 'Set the tag that the work can not contain', 233 | '設定作品不能包含的tag' 234 | ], 235 | '_不能含有tag': [ 236 | '不能含有 tag ', 237 | '指定したタグを除外する', 238 | 'Exclude specified tag', 239 | '不能含有 tag ' 240 | ], 241 | '_排除tag的按钮_title': [ 242 | '在下载前,您可以设置想要排除的tag', 243 | 'ダウンロードする前に、除外するタグを設定できます', 244 | 'Before downloading, you can set the tag you want to exclude', 245 | '在下載前,您可以設定想要排除的tag' 246 | ], 247 | '_排除tag的提示文字': [ 248 | '您可在下载前设置要排除的tag,这样在下载时将不会下载含有这些tag的作品。区分大小写;如需排除多个tag,请使用英文逗号分隔。请注意要排除的tag的优先级大于要包含的tag的优先级。', 249 | 'ダウンロードする前に、除外するタグを設定できます。ケースセンシティブ;複数のタグを設定する必要がある場合は、\',\'を分けて使用できます。除外されたタグは、含まれているタグよりも優先されます', 250 | 'Before downloading, you can set the tag you want to exclude. Case sensitive; If you need to set multiple tags, you can use \',\' separated. The excluded tag takes precedence over the included tag', 251 | '您可在下載前設定要排除的tag,這樣在下載時將不會下載含有這些tag的作品。區分大小寫;如需排除多個tag,請使用英文逗號分隔。請注意要排除的tag的優先等級大於要包含的tag的優先等級。' 252 | ], 253 | '_设置了排除tag之后的提示': [ 254 | '本次任务设置了排除的tag:', 255 | 'このタスクはタグを除外します:', 256 | 'This task excludes tag:', 257 | '本次工作設定了排除的tag:' 258 | ], 259 | '_必须tag的按钮文字': [ 260 | '设置作品必须包含的tag', 261 | '作品に含める必要があるタグを設定する', 262 | 'Set the tag that the work must contain', 263 | '設定作品必須包含的tag' 264 | ], 265 | '_必须含有tag': [ 266 | '必须含有 tag ', 267 | 'タグを含める必要があります', 268 | 'Must contain tag', 269 | '必須含有 tag ' 270 | ], 271 | '_必须tag的按钮_title': [ 272 | '在下载前,您可以设置必须包含的tag。', 273 | 'ダウンロードする前に、含まれなければならないタグを設定することができます', 274 | 'Before downloading, you can set the tag that must be included', 275 | '在下載前,您可以設定必須包含的tag。' 276 | ], 277 | '_必须tag的提示文字': [ 278 | '您可在下载前设置作品里必须包含的tag,区分大小写;如需包含多个tag,请使用英文逗号分隔。', 279 | 'ダウンロードする前に、含まれなければならないタグを設定することができます。ケースセンシティブ;複数のタグを設定する必要がある場合は、\',\'を分けて使用できます。', 280 | 'Before downloading, you can set the tag that must be included. Case sensitive; If you need to set multiple tags, you can use \',\' separated. ', 281 | '您可在下載前設定作品裡必須包含的tag,區分大小寫;如需包含多個tag,請使用英文逗號分隔。' 282 | ], 283 | '_设置了必须tag之后的提示': [ 284 | '本次任务设置了必须的tag:', 285 | 'このタスクは、必要なタグを設定します:', 286 | 'This task set the necessary tag: ', 287 | '本次工作設定了必須的tag:' 288 | ], 289 | '_筛选宽高的按钮文字': [ 290 | '设置宽高条件', 291 | '幅と高さの条件を設定する', 292 | 'Set the width and height', 293 | '設定寬高條件' 294 | ], 295 | '_筛选宽高的按钮_title': [ 296 | '在下载前,您可以设置要下载的图片的宽高条件。', 297 | 'ダウンロードする前に、ダウンロードする写真の幅と高さの条件を設定できます。', 298 | 'Before downloading, you can set the width and height conditions of the pictures you want to download.', 299 | '在下載前,您可以設定要下載的圖片的寬高條件。' 300 | ], 301 | '_设置宽高比例': [ 302 | '设置宽高比例', 303 | '縦横比を設定する', 304 | 'Set the aspect ratio', 305 | '設定寬高比例' 306 | ], 307 | '_设置宽高比例_title': [ 308 | '设置宽高比例,也可以手动输入宽高比', 309 | '縦横比を設定するか、手動で縦横比を入力します', 310 | 'Set the aspect ratio, or manually enter the aspect ratio', 311 | '設定寬高比,也可以手動輸入寬高比' 312 | ], 313 | '_不限制': [ 314 | '不限制', 315 | '無制限', 316 | 'not limited', 317 | '不限制' 318 | ], 319 | '_横图': [ 320 | '横图', 321 | '横の絵', 322 | 'Horizontal picture', 323 | '橫圖' 324 | ], 325 | '_竖图': [ 326 | '竖图', 327 | '縦の絵', 328 | 'Vertical picture', 329 | '豎圖' 330 | ], 331 | '_输入宽高比': [ 332 | '宽高比 >=', 333 | '縦横比 >=', 334 | 'Aspect ratio >=', 335 | '寬高比 >=', 336 | ], 337 | '_设置了宽高比之后的提示': [ 338 | '本次任务设置了宽高比:{}', 339 | 'このタスクは縦横比を設定します:{}', 340 | 'This task sets the aspect ratio: {}', 341 | '本次工作設定了寬高比:{}' 342 | ], 343 | '_宽高比必须是数字': [ 344 | '宽高比必须是数字', 345 | '縦横比は数値でなければなりません', 346 | 'The aspect ratio must be a number', 347 | '寬高比必須是數字' 348 | ], 349 | '_筛选宽高的提示文字': [ 350 | '请输入最小宽度和最小高度,不会下载不符合要求的图片。', 351 | '最小幅と最小高さを入力してください。要件を満たしていない画像はダウンロードされません。', 352 | 'Please enter the minimum width and minimum height. Will not download images that do not meet the requirements', 353 | '請輸入最小寬度和最小高度,不會下載不符合要求的圖片。' 354 | ], 355 | '_本次输入的数值无效': [ 356 | '本次输入的数值无效', 357 | '無効な入力', 358 | 'Invalid input', 359 | '本次輸入的數值無效' 360 | ], 361 | '_设置成功': [ 362 | '设置成功', 363 | 'セットアップが正常に完了しました', 364 | 'Set up successfully', 365 | '設定成功' 366 | ], 367 | '_设置了筛选宽高之后的提示文字p1': [ 368 | '本次任务设置了过滤宽高条件:宽度>=', 369 | 'この作業では、フィルターの幅と高さの条件を設定します。幅≥', 370 | 'This task sets the filter width and height conditions. Width ≥', 371 | '本次工作設定了篩選寬高條件:寬度>=' 372 | ], 373 | '_或者': [ 374 | ' 或者 ', 375 | ' または ', 376 | ' or ', 377 | ' 或是 ' 378 | ], 379 | '_并且': [ 380 | ' 并且 ', 381 | ' そして ', 382 | ' and ', 383 | ' 並且 ' 384 | ], 385 | '_高度设置': [ 386 | '高度>=', 387 | '高さ≥', 388 | 'height ≥', 389 | '高度>=' 390 | ], 391 | '_个数': [ 392 | '设置作品数量', 393 | '作品数を設定する', 394 | 'Set the number of works', 395 | '設定作品數量' 396 | ], 397 | '_页数': [ 398 | '设置页面数量', 399 | 'ページ数を設定する', 400 | 'Set the number of pages', 401 | '設定頁面數量' 402 | ], 403 | '_页数提示': [ 404 | '请输入要获取的页数', 405 | '取得するページ数を入力してください', 406 | 'Please enter the number of pages to get', 407 | '請輸入要取得的頁數' 408 | ], 409 | '_筛选收藏数的按钮文字': [ 410 | '设置收藏数量', 411 | 'お気に入りの数を設定する', 412 | 'Set the bookmarkCount conditions', 413 | '設定收藏數量' 414 | ], 415 | '_筛选收藏数的按钮_title': [ 416 | '在下载前,您可以设置对收藏数量的要求。', 417 | 'ダウンロードする前に、お気に入り数の要件を設定することができます。', 418 | 'Before downloading, You can set the requirements for the number of bookmarks.', 419 | '在下載前,您可以設定對收藏數量的要求。' 420 | ], 421 | '_筛选收藏数_center': [ 422 | '设置收藏数量', 423 | 'ブックマークの数を設定する', 424 | 'Set the number of bookmarks', 425 | '設定收藏數量' 426 | ], 427 | '_筛选收藏数的提示_center': [ 428 | '如果作品的收藏数小于设置的数字,作品不会被下载。', 429 | '作品のブックマークの数が設定された数よりも少ない場合、作品はダウンロードされません。', 430 | 'If the number of bookmarks of the work is less than the set number, the work will not be downloaded.', 431 | '如果作品的收藏數小於設定的數字,作品不會被下載。' 432 | ], 433 | '_筛选收藏数的提示文字': [ 434 | '请输入一个数字,如果作品的收藏数小于这个数字,作品不会被下载。', 435 | '数字を入力してください。 作品のブックマークの数がこの数より少ない場合、作品はダウンロードされません。', 436 | 'Please enter a number. If the number of bookmarks of the work is less than this number, the work will not be downloaded.', 437 | '請輸入一個數字,如果作品的收藏數小於這個數字,作品不會被下載。' 438 | ], 439 | '_设置了筛选收藏数之后的提示文字': [ 440 | '本次任务设置了收藏数条件:收藏数>=', 441 | 'このタスクは、お気に入りの数を設定します。条件:お気に入りの数≥', 442 | 'This task sets the number of bookmarks condition: number of bookmarks ≥', 443 | '本次工作設定了收藏數條件:收藏數>=' 444 | ], 445 | '_本次任务已全部完成': [ 446 | '本次任务已全部完成。', 447 | 'このタスクは完了しました。', 448 | 'This task has been completed.', 449 | '本次工作已全部完成' 450 | ], 451 | '_当前任务尚未完成1': [ 452 | '当前任务尚未完成,请等到提示完成之后再设置新的任务。', 453 | '現在のタスクはまだ完了していません。お待ちください。', 454 | 'The current task has not yet completed, please wait.', 455 | '目前工作尚未完成,請等到提示完成之後再設定新的工作。' 456 | ], 457 | '_check_want_page_rule1_arg1': [ 458 | '从本页开始下载
如果要下载全部作品,请保持默认值。
如果需要设置下载的作品数,请输入从1开始的数字,1为仅下载当前作品。', 459 | 'このページからダウンロードする
すべての作品をダウンロードしたい場合は、デフォルト値のままにしてください。
ダウンロード数を設定する必要がある場合は、1から始まる番号を入力します。 現在の作品には1の番号が付けられています。', 460 | 'Download from this page
If you want to download all the work, please leave the default value.
If you need to set the number of downloads, enter a number starting at 1. The current works are numbered 1.', 461 | '從本頁開始下載
如果要下載全部作品,請保持預設值。
如果需要設定下載的作品數,請輸入從1開始的數字,1為僅下載目前作品。' 462 | ], 463 | '_check_want_page_rule1_arg2': [ 464 | '参数不合法,本次操作已取消。
', 465 | 'パラメータは有効ではありません。この操作はキャンセルされました。
', 466 | 'Parameter is not legal, this operation has been canceled.
', 467 | '參數不合法,本次動作已取消。
' 468 | ], 469 | '_check_want_page_rule1_arg3': [ 470 | '任务开始
本次任务条件: 从本页开始下载-num-个作品', 471 | 'タスクが開始されます。
このタスク条件:このページから-num-枚の作品をダウンロード。', 472 | 'Task starts.
This task condition: Download -num- works from this page.', 473 | '工作開始
本次工作條件: 從本頁開始下載-num-個作品' 474 | ], 475 | '_check_want_page_rule1_arg4': [ 476 | '任务开始
本次任务条件: 向下获取所有作品', 477 | 'タスクが開始されます。
このタスク条件:このページからすべての作品をダウンロードする。', 478 | 'Task starts.
This task condition: download all the work from this page.', 479 | '工作開始
本次工作條件: 向下取得所有作品' 480 | ], 481 | '_check_want_page_rule1_arg5': [ 482 | '从本页开始下载
如果不限制下载的页数,请不要修改此默认值。
如果要限制下载的页数,请输入从1开始的数字,1为仅下载本页。', 483 | 'このページからダウンロードする
ダウンロードしたページ数を制限しない場合は、デフォルト値のままにしておきます。
ダウンロードするページ数を設定する場合は、1から始まる番号を入力します。 現在のページは1です。', 484 | 'Download from this page
If you do not limit the number of pages downloaded, leave the default value.
If you want to set the number of pages to download, enter a number starting at 1. This page is 1.', 485 | '從本頁開始下載
如果不限制下載的頁數,請不要變更此預設值。
如果要限制下載的頁數,請輸入從1開始的數字,1為僅下載本頁。' 486 | ], 487 | '_check_want_page_rule1_arg8': [ 488 | '从本页开始下载
如果要限制下载的页数,请输入从1开始的数字,1为仅下载本页。', 489 | 'このページからダウンロードする
ダウンロードするページ数を設定する場合は、1から始まる番号を入力します。 現在のページは1です。', 490 | 'Download from this page
If you want to set the number of pages to download, enter a number starting at 1. This page is 1.', 491 | '從本頁開始下載
如果要限制下載的頁數,請輸入從1開始的數字,1為僅下載本頁。' 492 | ], 493 | '_check_want_page_rule1_arg6': [ 494 | '任务开始
本次任务条件: 从本页开始下载-num-页', 495 | 'タスクが開始されます。
このタスク条件:現在のページから-num-ページ', 496 | 'Task starts.
This task condition: download -num- pages from the current page', 497 | '工作開始
本次工作條件: 從本頁開始下載-num-頁' 498 | ], 499 | '_check_want_page_rule1_arg7': [ 500 | '任务开始
本次任务条件: 下载所有页面', 501 | 'タスクが開始されます。
このタスク条件:すべてのページをダウンロード', 502 | 'Task starts.
This task condition: download all pages', 503 | '工作開始
本次工作條件: 下載所有頁面' 504 | ], 505 | '_请输入最低收藏数和要抓取的页数': [ 506 | '请输入最低收藏数和要抓取的页数,用英文逗号分开。\n类似于下面的形式: \n1000,1000', 507 | 'お気に入りの最小数とクロールするページ数を,\',\'で区切って入力してください。\n例えば:\n1000,1000', 508 | 'Please enter the minimum number of bookmarks, and the number of pages to be crawled, separated by \',\'.\nE.g:\n1000,1000', 509 | '請輸入最低收藏數和要擷取的頁數,用英文逗號分開。\n類似於下面的形式: \n1000,1000' 510 | ], 511 | '_参数不合法1': [ 512 | '参数不合法,请稍后重试。', 513 | 'パラメータが合法ではありません。後でやり直してください。', 514 | 'Parameter is not legal, please try again later.', 515 | '參數不合法,請稍後重試。' 516 | ], 517 | '_tag搜索任务开始': [ 518 | '任务开始
本次任务条件: 收藏数不低于{},向下抓取{}页', 519 | 'タスクが開始されます。
このタスク条件:ブックマークの数は{}ページ以上で、{}ページがクロールされます。', 520 | 'Task starts.
This task condition: the number of bookmarks is not less than {}, {} pages down to crawl.', 521 | '工作開始
本次工作條件: 收藏數不低於{},向下擷取{}頁' 522 | ], 523 | '_want_page_弹出框文字_page_type10': [ 524 | '您想要下载多少页?请输入数字。\r\n当前模式下,列表页的页数最多只有', 525 | 'ダウンロードしたいページ数を入力してください。 \r\n最大値:', 526 | 'Please enter the number of pages you want to download.\r\n The maximum value is ', 527 | '您想要下載多少頁?請輸入數字。\r\n目前模式下,清單頁的頁數最多只有' 528 | ], 529 | '_输入超过了最大值': [ 530 | '您输入的数字超过了最大值', 531 | '入力した番号が最大値を超えています', 532 | 'The number you entered exceeds the maximum', 533 | '您輸入的數字超過了最大值' 534 | ], 535 | '_多图作品下载张数': [ 536 | '多图作品将下载前{}张图片', 537 | '2枚以上の作品,最初の{}枚の写真をダウンロードする', 538 | 'Multi-artwork will download the first {} pictures', 539 | '多圖作品將下載前{}張圖片' 540 | ], 541 | '_任务开始1': [ 542 | '任务开始
本次任务条件: 从本页开始下载{}页', 543 | 'タスクが開始されます。
このタスク条件:このページから{}ページをダウンロードする', 544 | 'Task starts.
This task condition: download {} pages from this page', 545 | '工作開始
本次工作條件: 從本頁開始下載{}頁' 546 | ], 547 | '_任务开始0': [ 548 | '任务开始', 549 | 'タスクが開始されます。', 550 | 'Task starts.', 551 | '工作開始' 552 | ], 553 | '_check_notdown_type_result1_弹窗': [ 554 | '由于您排除了所有作品类型,本次任务已取消。', 555 | 'すべての種類の作業を除外したため、タスクはキャンセルされました。', 556 | 'Because you excluded all types of work, the task was canceled.', 557 | '由於您排除了所有作品類型,本次工作已取消。' 558 | ], 559 | '_check_notdown_type_result1_html': [ 560 | '排除作品类型的设置有误,任务取消!', 561 | '作業タイプの除外にエラー設定がありました。 タスクがキャンセルされました。', 562 | 'There was an error setting for the exclusion of the work type. Task canceled.', 563 | '排除作品類型的設定有誤,工作取消!' 564 | ], 565 | '_check_notdown_type_result2_弹窗': [ 566 | '由于作品类型的设置有误,本次任务已取消。', 567 | '除外タイプを設定する際にエラーが発生しました。 タスクがキャンセルされました。', 568 | 'There was an error setting for the exclusion of the work type. Task canceled.', 569 | '由於作品類型的設定有誤,本次工作已取消。' 570 | ], 571 | '_check_notdown_type_result3_html': [ 572 | '本次任务设置了排除作品类型:', 573 | 'このダウンロードでは、このタイプの作品は除外されます:', 574 | 'This task excludes these types of works:', 575 | '本次工作設定了排除作品類型:' 576 | ], 577 | '_单图': [ 578 | '单图 ', 579 | '1枚の作品', 580 | 'one images', 581 | '單圖 ' 582 | ], 583 | '_多图': [ 584 | '多图 ', 585 | '2枚以上の作品', 586 | 'multiple images', 587 | '多圖 ' 588 | ], 589 | '_动图': [ 590 | '动图 ', 591 | 'うごイラ', 592 | 'GIF', 593 | '動圖 ' 594 | ], 595 | '_tag搜索页已抓取多少页': [ 596 | '已抓取本次任务第{}/{}页,当前加载到第{}页', 597 | '{}/{}ページをクロールしています。 現在のページ番号は{}ページです', 598 | 'Has been crawling {} / {} pages. The current page number is page {}', 599 | '已擷取本次工作第{}/{}頁,目前載入到第{}頁' 600 | ], 601 | '_tag搜索页任务完成1': [ 602 | '本次任务完成。当前有{}张作品。', 603 | 'この作業は完了です。 今は{}枚の作品があります。', 604 | 'This task is completed. There are now {} works.', 605 | '本次工作完成。目前有{}張作品。' 606 | ], 607 | '_tag搜索页任务完成2': [ 608 | '已抓取本tag的所有页面,本次任务完成。当前有{}张作品。', 609 | 'この作業は完了です。 今は{}枚の作品があります。', 610 | 'This task is completed. There are now {} works.', 611 | '已擷取本tag的所有頁面,本次工作完成。目前有{}張作品。' 612 | ], 613 | '_tag搜索页中断': [ 614 | '当前任务已中断!
当前有{}张作品。', 615 | '現在のタスクが中断されました。
今は{}枚の作品があります。', 616 | 'The current task has been interrupted.
There are now {} works.', 617 | '目前工作已中斷!
目前有{}張作品。' 618 | ], 619 | '_排行榜进度': [ 620 | '已抓取本页面第{}部分', 621 | 'このページの第{}部がクロールされました', 622 | 'Part {} of this page has been crawled', 623 | '已擷取本頁面第{}部分' 624 | ], 625 | '_排行榜任务完成': [ 626 | '本页面抓取完成。当前有{}张作品,开始获取作品信息。', 627 | 'このページはクロールされ、{}個の作品があります。 詳細は作品を入手し始める。', 628 | 'This page is crawled and now has {} works. Start getting the works for more information.', 629 | '本頁面擷取完成。目前有{}張作品,開始取得作品資訊。' 630 | ], 631 | '_列表页获取完成2': [ 632 | '列表页获取完成。
当前有{}张作品,开始获取作品信息。', 633 | 'リストページがクロールされます。
{}個の作品があります。 詳細は作品を入手し始める。', 634 | 'The list page gets done.
Now has {} works. Start getting the works for more information.', 635 | '清單頁取得完成。
目前有{}張作品,開始取得作品資訊。' 636 | ], 637 | '_列表页抓取进度': [ 638 | '已抓取列表页{}个页面', 639 | '{}のリストページを取得しました', 640 | 'Has acquired {} list pages', 641 | '已擷取清單頁{}個頁面' 642 | ], 643 | '_列表页抓取完成': [ 644 | '列表页面抓取完成,开始获取图片网址', 645 | 'リストページがクロールされ、画像URLの取得が開始されます', 646 | 'The list page is crawled and starts to get the image URL', 647 | '清單頁面擷取完成,開始取得圖片網址' 648 | ], 649 | '_列表页抓取结果为零': [ 650 | '抓取完毕,但没有找到符合筛选条件的作品。', 651 | 'クロールは終了しましたが、フィルタ条件に一致する作品が見つかりませんでした。', 652 | 'Crawl finished but did not find works that match the filter criteria.', 653 | '擷取完畢,但沒有找到符合篩選條件的作品。' 654 | ], 655 | '_排行榜列表页抓取遇到404': [ 656 | '本页面抓取完成。当前有{}张作品,开始获取作品信息。', 657 | 'このページはクロールされます、{}個の作品があります。 詳細は作品を入手し始める。', 658 | 'This page is crawled. Now has {} works. Start getting the works for more information.', 659 | '本頁面擷取完成。目前有{}張作品,開始取得作品資訊。' 660 | ], 661 | '_当前任务尚未完成2': [ 662 | '当前任务尚未完成,请等待完成后再下载。', 663 | '現在のタスクはまだ完了していません', 664 | 'The current task has not yet been completed', 665 | '目前工作尚未完成,請等待完成後再下載。' 666 | ], 667 | '_列表抓取完成开始获取作品页': [ 668 | '当前列表中有{}张作品,开始获取作品信息', 669 | '{}個の作品があります。 詳細は作品を入手し始める。', 670 | 'Now has {} works. Start getting the works for more information.', 671 | '目前清單中有{}張作品,開始取得作品資訊' 672 | ], 673 | '_开始获取作品页面': [ 674 | '
开始获取作品页面', 675 | '
作品ページの取得を開始する', 676 | '
Start getting the works page', 677 | '
開始取得作品頁面' 678 | ], 679 | '_无权访问1': [ 680 | '无权访问{},抓取中断。', 681 | 'アクセス{}、中断はありません。', 682 | 'No access {}, interruption.', 683 | '無權造訪{},擷取中斷。' 684 | ], 685 | '_无权访问2': [ 686 | '无权访问{},跳过该作品。', 687 | 'アクセス{}、無視する。', 688 | 'No access {}, skip.', 689 | '無權造訪{},跳過該作品。' 690 | ], 691 | '_作品页状态码0': [ 692 | '请求的url不可访问', 693 | '要求されたURLにアクセスできません', 694 | 'The requested url is not accessible', 695 | '要求的url無法造訪' 696 | ], 697 | '_作品页状态码400': [ 698 | '该作品已被删除', 699 | '作品は削除されました', 700 | 'The work has been deleted', 701 | '該作品已被刪除' 702 | ], 703 | '_作品页状态码403': [ 704 | '无权访问请求的url 403', 705 | 'リクエストされたURLにアクセスできない 403', 706 | 'Have no access to the requested url 403', 707 | '無權造訪要求的url 403' 708 | ], 709 | '_作品页状态码404': [ 710 | '404 not found', 711 | '404 not found', 712 | '404 not found', 713 | '404 not found' 714 | ], 715 | '_抓取图片网址的数量': [ 716 | '已获取{}个图片网址', 717 | '{}つの画像URLを取得', 718 | 'Get {} image URLs', 719 | '已取得{}個圖片網址' 720 | ], 721 | '_正在抓取': [ 722 | '正在抓取,请等待……', 723 | '取得中、しばらくお待ちください...', 724 | 'Getting, please wait...', 725 | '正在擷取,請等待……' 726 | ], 727 | '_获取全部书签作品': [ 728 | '获取全部书签作品,时间可能比较长,请耐心等待。', 729 | 'ブックマークしたすべての作品を入手すると、時間がかかることがあります。お待ちください。', 730 | 'Get all bookmarked works, the time may be longer, please wait.', 731 | '取得全部書籤作品,時間可能比較長,請耐心等待。' 732 | ], 733 | '_抓取图片网址遇到中断': [ 734 | '当前任务已中断!', 735 | '現在のタスクが中断されました。', 736 | 'The current task has been interrupted.', 737 | '目前工作已中斷!' 738 | ], 739 | '_收起下载按钮': [ 740 | '收起下载按钮', 741 | 'ダウンロードボタンを非表示にする', 742 | '', 743 | '摺疊下載按鈕' 744 | ], 745 | '_展开下载按钮': [ 746 | '展开下载按钮', 747 | 'ダウンロードボタンを表示', 748 | '', 749 | '展開下載按鈕' 750 | ], 751 | '_展开收起下载按钮_title': [ 752 | '展开/收起下载按钮', 753 | 'ダウンロードボタンを表示/非表示', 754 | 'Show / hide download button', 755 | '展開/摺疊下載按鈕' 756 | ], 757 | '_关闭': [ 758 | '关闭', 759 | 'クローズド', 760 | 'close', 761 | '關閉' 762 | ], 763 | '_输出信息': [ 764 | '输出信息', 765 | '出力情報', 766 | 'Output information', 767 | '輸出資訊' 768 | ], 769 | '_复制': [ 770 | '复制', 771 | 'コピー', 772 | 'Copy', 773 | '複製' 774 | ], 775 | '_已复制到剪贴板': [ 776 | '已复制到剪贴板,可直接粘贴', 777 | 'クリップボードにコピーされました', 778 | 'Has been copied to the clipboard', 779 | '已複製至剪貼簿,可直接貼上' 780 | ], 781 | '_下载设置': [ 782 | '下载设置', 783 | '設定をダウンロードする', 784 | 'Download settings', 785 | '下載設定' 786 | ], 787 | '_隐藏': [ 788 | '隐藏', 789 | '隠された', 790 | 'hide', 791 | '隱藏' 792 | ], 793 | '_收起展开设置项': [ 794 | '收起/展开设置项', 795 | '設定の折りたたみ/展開', 796 | 'Collapse/expand settings', 797 | '摺疊/展開設定項目' 798 | ], 799 | '_Github': [ 800 | 'Github 页面,欢迎 star', 801 | 'Githubのページ、starをクリックしてください', 802 | 'Github page, if you like, please star it', 803 | 'Github 頁面,歡迎 star' 804 | ], 805 | '_扩展提示': [ 806 | '推荐使用本工具的浏览器扩展程序。
如果脚本版下载图片失败,请安装浏览器扩展程序。
因为两者不能同时运行,所以安装扩展版之后,必须禁用脚本版。
最后重启浏览器即可使用。', 807 | 'このツールのブラウザ拡張機能を使用することをお勧めします。
スクリプトバージョンで画像のダウンロードに失敗した場合は、ブラウザ拡張をインストールしてください。
2つを同時に実行することはできないため、拡張機能をインストールした後にスクリプトバージョンを無効にする必要があります。
最後にブラウザを再起動して使用します。', 808 | 'It is recommended to use the browser extension of this tool.
If the script version fails to download the image, please install the browser extension.
Because the two cannot run at the same time, the script version must be disabled after installing the extension.
Finally restart the browser to use.', 809 | '推薦使用本工具的瀏覽器擴展程序。
如果腳本版下載圖片失敗,請安裝瀏覽器擴展程序。
因為兩者不能同時運行,所以安裝擴展版之後,必須禁用腳本版。
最後重啟瀏覽器即可使用。' 810 | ], 811 | '_扩展提示2': [ 812 | '我推荐您使用本工具的 Chrome 浏览器的扩展程序,它有更好的使用体验。
前往安装页面 Wiki
安装扩展版之后,你需要禁用这个脚本版,并且重启浏览器。', 813 | '当ツールのChromeブラウザの拡張プログラムをお勧めします。より良い体験ができます。
インストールページへ Wiki
拡張版をインストールするには、このバージョンを使用を禁止し、ブラウザを再起動する必要があります。', 814 | 'I recommend using the Chrome extension for this tool, which has a better experience.
Go to the installation page Wiki
After installing the extension, you need to disable this script version and restart the browser.', 815 | '我推薦您使用本工具的 Chrome 瀏覽器擴展程序,它有更好的使用體驗。
前往安装页面 Wiki
安裝擴展版之後,你需要禁用這個腳本版,并且重啟瀏覽器。' 816 | ], 817 | '_快捷键切换显示隐藏': [ 818 | '使用 Alt + X,可以显示和隐藏下载面板', 819 | 'Alt + Xを使用してダウンロードパネルを表示および非表示にする', 820 | 'Use Alt + X to show and hide the download panel', 821 | '使用 Alt + X,可以顯示和隱藏下載面板' 822 | ], 823 | '_设置命名规则': [ 824 | '共抓取到{}个图片,请设置文件命名规则:', 825 | '合計{}枚の画像を取得し、ファイルの命名規則を設定してください:', 826 | 'Grab a total of {} pictures, please set the file naming rules: ', 827 | '共擷取到{}個圖片,請設定檔案命名規則:' 828 | ], 829 | '_设置命名规则3': [ 830 | '共抓取到 {} 个图片', 831 | '合計 {} 枚の画像を取得し', 832 | 'Grab a total of {} pictures', 833 | '共擷取到 {} 個圖片' 834 | ], 835 | '_设置文件名': [ 836 | '设置命名规则', 837 | '命名規則を設定する', 838 | 'Set naming rules', 839 | '設定命名規則' 840 | ], 841 | '_设置文件夹名的提示': [ 842 | `可以使用 '/' 建立文件夹
示例:{p_title}/{user}/{id}`, 843 | `フォルダは '/'で作成できます
例:{p_title}/{user}/{id}`, 844 | `You can create a folder with '/'
Example:{p_title}/{user}/{id}`, 845 | `可以使用 '/' 建立資料夾
範例:{p_title}/{user}/{id}` 846 | ], 847 | '_添加标记名称': [ 848 | '添加标记名称', 849 | 'タグ名を追加する', 850 | 'Add tag name', 851 | '加入標記名稱' 852 | ], 853 | '_添加标记名称提示': [ 854 | '把标签名称添加到文件名里', 855 | 'ファイル名にタグ名を追加する', 856 | 'Add the tag name to the file name', 857 | '將標籤名稱加到檔名中' 858 | ], 859 | '_如何建立文件夹': [ 860 | '允许 TM 创建文件夹', 861 | 'TMにフォルダの作成を許可する', 862 | 'Allow TM to create folders', 863 | '設置 TM 以建立資料夾', 864 | ], 865 | '_文件夹提示网址': [ 866 | 'https://s1.ax1x.com/2018/11/13/iOcXDK.png', 867 | 'https://s1.ax1x.com/2018/11/13/iOcOu6.png', 868 | 'https://s1.ax1x.com/2018/11/13/iOcbg1.png', 869 | 'https://s1.ax1x.com/2018/11/13/iOcqjx.png', 870 | ], 871 | '_ff不能建立文件夹': [ 872 | '要在 Firefox 上建立文件夹,请使用扩展版。', 873 | 'Firefoxでフォルダを作成するには、拡張バージョンを使用してください。', 874 | 'To create a folder on Firefox, use the extended version.', 875 | '要在 Firefox 上建立文件夾,請使用擴展版。', 876 | ], 877 | '_查看标记的含义': [ 878 | '查看标记的含义', 879 | 'タグの意味を表示する', 880 | 'View the meaning of the tag', 881 | '檢視標記的意義' 882 | ], 883 | '_可用标记1': [ 884 | '默认文件名,如 44920385_p0', 885 | 'デフォルトのファイル名,例 44920385_p0', 886 | 'Default file name, for example 44920385_p0', 887 | '預設檔案名稱,如 44920385_p0' 888 | ], 889 | '_可用标记9': [ 890 | '数字 id,如 44920385', 891 | '44920385 などの番号 ID', 892 | 'Number id, for example 44920385', 893 | '數字 id,如 44920385' 894 | ], 895 | '_可用标记10': [ 896 | '图片在作品内的序号,如 0、1、2、3……', 897 | '0、1、2、3など、作品の写真のシリアル番号。', 898 | 'The serial number of the picture in the work, such as 0, 1, 2, 3...', 899 | '圖片在作品內的序號,如 0、1、2、3……' 900 | ], 901 | '_可用标记2': [ 902 | '作品标题', 903 | '作品のタイトル', 904 | 'works title', 905 | '作品標題' 906 | ], 907 | '_可用标记3': [ 908 | '作品的 tag 列表', 909 | '作品の tags', 910 | 'Tags of works', 911 | '作品的 tag 清單' 912 | ], 913 | '_可用标记4': [ 914 | '画师名字', 915 | 'アーティスト名', 916 | 'Artist name', 917 | '畫師名稱' 918 | ], 919 | '_可用标记6': [ 920 | '画师 id', 921 | 'アーティスト ID', 922 | 'Artist id', 923 | '畫師 id' 924 | ], 925 | '_可用标记7': [ 926 | '宽度和高度', 927 | '幅と高さ', 928 | 'width and height', 929 | '寬度和高度' 930 | ], 931 | '_可用标记8': [ 932 | 'bookmark-count,作品的收藏数。把它放在最前面就可以让下载后的文件按收藏数排序。', 933 | 'bookmark-count,作品のコレクション数のコレクション数は。', 934 | 'bookmark-count.', 935 | 'bookmark-count,作品的收藏數。將它放在最前面就可以讓下載後的檔案依收藏數排序。' 936 | ], 937 | '_可用标记5': [ 938 | '您可以使用多个标记;建议在不同标记之间添加分割用的字符。示例:{id}-{userid}-{px}
* 在某些情况下,会有一些标记不可用。', 939 | '複数のタグを使用することができ;異なるタグ間に別の文字を追加することができます。例:{id}-{userid}-{px}
* 場合によっては、一部のタグが利用できず。', 940 | 'You can use multiple tags, and you can add a separate character between different tags. Example: {id}-{userid}-{px}
* In some cases, some tags will not be available.', 941 | '您可以使用多個標記;建議在不同標記之間加入分隔用的字元。範例:{id}-{userid}-{px}
* 在某些情況下,會有一些標記不可用。' 942 | ], 943 | '_文件夹标记_p_user': [ 944 | '当前页面的画师名字', 945 | 'アーティスト名', 946 | 'Artist name of this page', 947 | '目前頁面的畫師名稱' 948 | ], 949 | '_文件夹标记_p_uid': [ 950 | '当前页面的画师id', 951 | 'アーティストID', 952 | 'Artist id of this page', 953 | '目前頁面的畫師id' 954 | ], 955 | '_文件夹标记_p_tag': [ 956 | '当前页面的 tag', 957 | '現在のタグ', 958 | 'Current tag', 959 | '目前頁面的 tag' 960 | ], 961 | '_文件夹标记_p_title': [ 962 | '当前页面的标题', 963 | 'ページのタイトル', 964 | 'The title of this page', 965 | '目前頁面的標題' 966 | ], 967 | '_预览文件名': [ 968 | '预览文件名', 969 | 'ファイル名のプレビュー', 970 | 'Preview file name', 971 | '預覽檔案名稱' 972 | ], 973 | '_设置下载线程': [ 974 | '设置下载线程', 975 | 'ダウンロードスレッドを設定する', 976 | 'Set the download thread', 977 | '設定下載執行緒' 978 | ], 979 | '_线程数字': [ 980 | '可以输入 1-10 之间的数字,设置同时下载的数量', 981 | '同時ダウンロード数を設定するには、1〜10の数値を入力します', 982 | 'You can enter a number between 1-10 to set the number of concurrent downloads', 983 | '可以輸入 1-10 之間的數字,設定同時下載的數量' 984 | ], 985 | '_下载按钮1': [ 986 | '开始下载', 987 | 'start download', 988 | 'start download', 989 | '開始下載' 990 | ], 991 | '_下载按钮2': [ 992 | '暂停下载', 993 | 'puse download', 994 | 'puse download', 995 | '暫停下載' 996 | ], 997 | '_下载按钮3': [ 998 | '停止下载', 999 | 'stop download', 1000 | 'stop download', 1001 | '停止下載' 1002 | ], 1003 | '_下载按钮4': [ 1004 | '复制url', 1005 | 'copy urls', 1006 | 'copy urls', 1007 | '複製url' 1008 | ], 1009 | '_当前状态': [ 1010 | '当前状态 ', 1011 | '現在の状態 ', 1012 | 'Now state ', 1013 | '目前狀態 ' 1014 | ], 1015 | '_未开始下载': [ 1016 | '未开始下载', 1017 | 'まだダウンロードを開始していません', 1018 | 'Not yet started downloading', 1019 | '未開始下載' 1020 | ], 1021 | '_下载进度:': [ 1022 | '下载进度:', 1023 | 'ダウンロードの進捗状況:', 1024 | 'Download progress: ', 1025 | '下載進度:' 1026 | ], 1027 | '_下载线程:': [ 1028 | '下载线程:', 1029 | 'スレッド:', 1030 | 'Thread: ', 1031 | '下載執行緒:' 1032 | ], 1033 | '_查看下载说明': [ 1034 | '查看下载说明', 1035 | '指示の表示', 1036 | 'View instructions', 1037 | '檢視下載說明' 1038 | ], 1039 | '_下载说明': [ 1040 | '下载的文件保存在浏览器的下载目录里。
.ugoira 后缀名的文件是动态图的源文件,可以使用软件 HoneyView 查看。
请不要在浏览器的下载选项里选中\'总是询问每个文件的保存位置\'。
如果作品标题或tag里含有不能做文件名的字符,会被替换成下划线_。
如果下载进度卡住不动了,您可以先点击“暂停下载”按钮,之后点击“开始下载”按钮,尝试继续下载。
QQ群:499873152', 1041 | 'ダウンロードしたファイルは、ブラウザのダウンロードディレクトリに保存されます。
.ugoiraサフィックスファイルは、動的グラフのソースファイルです,ソフトウェア HoneyView を使用して表示することができます。
ダウンロードの進行状況が継続できない場合は、[ダウンロードの一時停止]ボタンをクリックし、[ダウンロードの開始]ボタンをクリックしてダウンロードを続行します。', 1042 | 'The downloaded file is saved in the browser`s download directory.
The .ugoira suffix file is the source file for the dynamic graph, Can be viewed using the software HoneyView.
If the download progress is stuck, you can click the "Pause Download" button and then click the "Start Download" button to try to continue the download.', 1043 | '下載的檔案儲存在瀏覽器的下載目錄裡。
.ugoira 尾碼的檔案是動態圖的原始檔,可以使用軟體 HoneyView 查看。
請不要在瀏覽器的下載選項裡選取\'總是詢問每個檔案的儲存位置\'。
如果作品標題或tag裡含有不能做檔名的字元,會被取代成下劃線_。
如果下載進度卡住不動了,您可以先點擊“暫停下載”按鈕,之後點擊“開始下載”按鈕,嘗試繼續下載。' 1044 | ], 1045 | '_正在下载中': [ 1046 | '正在下载中', 1047 | 'ダウンロード', 1048 | 'downloading', 1049 | '正在下載' 1050 | ], 1051 | '_下载完毕': [ 1052 | '下载完毕!', 1053 | 'ダウンロードが完了しました', 1054 | 'Download finished', 1055 | '下載完畢!' 1056 | ], 1057 | '_已暂停': [ 1058 | '下载已暂停', 1059 | 'ダウンロードは一時停止中です', 1060 | 'Download is paused', 1061 | '下載已暫停' 1062 | ], 1063 | '_已停止': [ 1064 | '下载已停止', 1065 | 'ダウンロードが停止しました', 1066 | 'Download stopped', 1067 | '下載已停止' 1068 | ], 1069 | '_已下载': [ 1070 | '已下载', 1071 | 'downloaded', 1072 | 'downloaded', 1073 | '已下載' 1074 | ], 1075 | '_获取图片网址完毕': [ 1076 | '获取完毕,共{}个图片地址', 1077 | '合計{}個の画像URLを取得する', 1078 | 'Get a total of {} image url', 1079 | '取得完畢,共{}個圖片網址' 1080 | ], 1081 | '_没有符合条件的作品': [ 1082 | '没有符合条件的作品!任务结束。', 1083 | '基準を満たす作品はありません!タスクは終了します。', 1084 | 'There are no works that meet the criteria! The task ends.', 1085 | '沒有符合條件的作品!工作結束。' 1086 | ], 1087 | '_没有符合条件的作品弹窗': [ 1088 | '抓取完毕!没有符合条件的作品!', 1089 | 'クロールが終了しました!基準を満たす作品はありません', 1090 | 'Crawl finished! There are no works that meet the criteria! ', 1091 | '擷取完畢!沒有符合條件的作品!' 1092 | ], 1093 | '_抓取完毕': [ 1094 | '抓取完毕!', 1095 | 'クロールが終了しました!', 1096 | 'Crawl finished!', 1097 | '擷取完畢!' 1098 | ], 1099 | '_快速下载本页': [ 1100 | '快速下载本页作品', 1101 | 'この作品をすばやくダウンロードする', 1102 | 'Download this work quickly', 1103 | '快速下載本頁作品' 1104 | ], 1105 | '_转换为 GIF': [ 1106 | '转换为 GIF', 1107 | 'GIFに変換する', 1108 | 'Convert to GIF', 1109 | '轉換為 GIF' 1110 | ], 1111 | '_准备转换': [ 1112 | '准备转换', 1113 | '変換する準備ができました', 1114 | 'Ready to convert', 1115 | '準備轉換' 1116 | ], 1117 | '_转换中请等待': [ 1118 | '转换中,请等待……', 1119 | '変換ではお待ちください...', 1120 | 'In the conversion, please wait...', 1121 | '轉換中,請稍候……' 1122 | ], 1123 | '_转换完成': [ 1124 | '转换完成', 1125 | '変換完了', 1126 | 'Conversion completed', 1127 | '轉換完成' 1128 | ], 1129 | '_从本页开始下载': [ 1130 | '从本页开始下载作品', 1131 | 'このページからダウンロードできます', 1132 | 'Download works from this page', 1133 | '從本頁開始下載作品' 1134 | ], 1135 | '_请留意文件夹命名': [ 1136 | '请留意文件夹命名', 1137 | 'フォルダの命名に注意してください', 1138 | 'Please pay attention to folder naming', 1139 | '請留意資料夾命名' 1140 | ], 1141 | '_下载相关作品': [ 1142 | '下载相关作品', 1143 | '関連作品をダウンロードする', 1144 | 'Download the related works', 1145 | '下載相關作品' 1146 | ], 1147 | '_相关作品大于0': [ 1148 | ' (下载相关作品必须大于 0)', 1149 | ' (ダウンロードする関連作品の数は0より大きくなければならない)', 1150 | ' (Download related works must be greater than 0)', 1151 | ' (下載相關作品必須大於 0)' 1152 | ], 1153 | '_下载作品': [ 1154 | '下载作品', 1155 | 'イメージをダウンロード', 1156 | 'Download works', 1157 | '下載作品' 1158 | ], 1159 | '_下载响应作品': [ 1160 | '下载响应作品', 1161 | 'イメージレスポンスの作品をダウンロードする', 1162 | 'Download the responses illustration', 1163 | '下載回應作品' 1164 | ], 1165 | '_下载该tag中的作品': [ 1166 | '下载该tag中的作品', 1167 | 'タグの作品をダウンロードする', 1168 | 'Download the work in the tag', 1169 | '下載該tag中的作品' 1170 | ], 1171 | '_下载书签': [ 1172 | '下载书签中的作品', 1173 | 'ブックマークされた作品をダウンロードする', 1174 | 'Download the works in this bookmark', 1175 | '下載書籤中的作品' 1176 | ], 1177 | '_默认下载多页': [ 1178 | ', 如有多页,默认会下载全部。', 1179 | '複数のページがある場合、デフォルトでダウンロードされます。', 1180 | ', If there are multiple pages, the default will be downloaded.', 1181 | ', 如有多頁,預設會下載全部。' 1182 | ], 1183 | '_调整完毕': [ 1184 | '调整完毕,当前有{}张作品。', 1185 | '調整が完了し、今、{}の作品があります。', 1186 | 'The adjustment is complete and now has {} works.', 1187 | '調整完畢,目前有{}張作品。' 1188 | ], 1189 | '_开始筛选': [ 1190 | '开始筛选', 1191 | 'スクリーニングを開始', 1192 | 'Start screening', 1193 | '開始篩選' 1194 | ], 1195 | '_开始筛选_title': [ 1196 | '按照设定来筛选当前tag里的作品。如果多次筛选,页码会一直累加。', 1197 | '現在のタグで作品をフィルタリングする。複数回フィルタリングすると、ページ番号は常に累積されます。', 1198 | 'Filter the work in the current tag. If you filter multiple times, the page number will increase.', 1199 | '按照設定來篩選當前tag裡的作品。如果多次篩選,頁碼會一直累加。' 1200 | ], 1201 | '_在结果中筛选': [ 1202 | '在结果中筛选', 1203 | '結果のフィルタリング', 1204 | 'Filter in results', 1205 | '在結果中篩選' 1206 | ], 1207 | '_在结果中筛选_title': [ 1208 | '如果本页筛选后作品太多,可以提高收藏数的要求,在结果中筛选。达不到要求的会被隐藏而不是删除。所以您可以反复进行筛选。被隐藏的项目不会被下载。', 1209 | 'あなたは何度も選別することができて、要求の作品が隠されて、それからダウンロードされません。', 1210 | 'You can make multiple screening , fail to meet the required works will be hidden, and will not be downloaded.', 1211 | '如果本頁篩選後作品太多,可以提高收藏數的要求,在結果中篩選。達不到要求的會被隱藏而不是刪除。所以您可以反覆進行篩選。被隱藏的項目不會被下載。' 1212 | ], 1213 | '_在结果中筛选弹窗': [ 1214 | '将在当前作品列表中再次过滤,请输入要求的最低收藏数: ', 1215 | '現在の作品リストで再度フィルタリングされます。要求された作品の最小数を入力してください', 1216 | 'Will be filtered again in the current list of works. Please enter the required minimum number of bookmarks:', 1217 | '將在目前作品清單中再次篩選,請輸入要求的最低收藏數:' 1218 | ], 1219 | '_下载当前作品': [ 1220 | '下载当前作品', 1221 | '現在の作品をダウンロードする', 1222 | 'Download the current work', 1223 | '下載目前作品' 1224 | ], 1225 | '_下载当前作品_title': [ 1226 | '下载当前列表里的所有作品', 1227 | '現在のリストにあるすべての作品をダウンロードする', 1228 | 'Download all the works in the current list', 1229 | '下載目前清單裡的所有作品' 1230 | ], 1231 | '_中断当前任务': [ 1232 | '中断当前任务', 1233 | '現在のタスクを中断する', 1234 | 'Interrupt the current task', 1235 | '中斷目前工作' 1236 | ], 1237 | '_中断当前任务_title': [ 1238 | '筛选时中断之后可以继续执行。', 1239 | 'ふるい分け作品で中断され、その後引き続き実行可能です。', 1240 | 'In the screening works when the break, then you can continue to perform.', 1241 | '篩選時中斷之後可以繼續執行。' 1242 | ], 1243 | '_当前任务已中断': [ 1244 | '当前任务已中断!', 1245 | '現在のタスクが中断されました', 1246 | 'The current task has been interrupted', 1247 | '目前工作已中斷!' 1248 | ], 1249 | '_下载时排除tag': [ 1250 | '下载时排除tag', 1251 | 'ダウンロード時にタグを除外する', 1252 | 'Exclude tags when downloading', 1253 | '下載時排除tag' 1254 | ], 1255 | '_清除多图作品': [ 1256 | '清除多图作品', 1257 | '複数の図面を削除する', 1258 | 'Remove multi-drawing works', 1259 | '清除多圖作品' 1260 | ], 1261 | '_清除多图作品_title': [ 1262 | '如果不需要可以清除多图作品', 1263 | '必要がない場合は、複数のグラフを削除することができます', 1264 | 'If you do not need it, you can delete multiple graphs', 1265 | '如果不需要可以清除多圖作品' 1266 | ], 1267 | '_清除动图作品': [ 1268 | '清除动图作品', 1269 | 'うごイラ作品を削除する', 1270 | 'Remove animat work', 1271 | '清除動圖作品' 1272 | ], 1273 | '_清除动图作品_title': [ 1274 | '如果不需要可以清除动图作品', 1275 | '必要がない場合は、うごイラを削除することができます', 1276 | 'If you do not need it, you can delete the animat work', 1277 | '如果不需要可以清除動圖作品' 1278 | ], 1279 | '_手动删除作品': [ 1280 | '手动删除作品', 1281 | 'マニュアル削除作品', 1282 | 'Manually delete the work', 1283 | '手動刪除作品' 1284 | ], 1285 | '_手动删除作品_title': [ 1286 | '可以在下载前手动删除不需要的作品', 1287 | 'ダウンロードする前に不要な作品を手動で削除することができます', 1288 | 'You can manually delete unwanted work before downloading', 1289 | '可以在下載前手動刪除不需要的作品' 1290 | ], 1291 | '_退出手动删除': [ 1292 | '退出手动删除', 1293 | '削除モードを終了する', 1294 | 'Exit manually delete', 1295 | '結束手動刪除' 1296 | ], 1297 | '_清空作品列表': [ 1298 | '清空作品列表', 1299 | '作品のリストを空にする', 1300 | 'Empty the list of works', 1301 | '清空作品清單' 1302 | ], 1303 | '_清空作品列表_title': [ 1304 | '如果网页内容过多,可能导致页面崩溃。如有需要可以清除当前的作品列表。', 1305 | '', 1306 | '', 1307 | '如果網頁內容過多,可能導致頁面當機。如有需要可以清除目前的作品清單。' 1308 | ], 1309 | '_下载本页作品': [ 1310 | '下载本页作品', 1311 | 'このページをダウンロードする', 1312 | 'Download this page works', 1313 | '下載本頁作品' 1314 | ], 1315 | '_下载本页作品_title': [ 1316 | '下载本页列表中的所有作品', 1317 | 'このページをダウンロードする', 1318 | 'Download this page works', 1319 | '下載本頁清單中的所有作品' 1320 | ], 1321 | '_已清除多图作品': [ 1322 | '已清除多图作品', 1323 | 'マルチマップ作品を削除しました', 1324 | 'Has deleted the multi-map works', 1325 | '已清除多圖作品' 1326 | ], 1327 | '_已清除动图作品': [ 1328 | '已清除动图作品', 1329 | 'うごイラが削除されました', 1330 | 'Dynamic work has been removed', 1331 | '已清除動圖作品' 1332 | ], 1333 | '_下载本排行榜作品': [ 1334 | '下载本排行榜作品', 1335 | 'このリストの作品をダウンロードする', 1336 | 'Download the works in this list', 1337 | '下載本排行榜作品' 1338 | ], 1339 | '_下载本排行榜作品_title': [ 1340 | '下载本排行榜的所有作品,包括现在尚未加载出来的。', 1341 | 'このリストの作品をダウンロードする、まだロードされていないものを含む', 1342 | 'Download all of the works in this list, including those that are not yet loaded.', 1343 | '下載本排行榜的所有作品,包括現在尚未載入出來的。' 1344 | ], 1345 | '_下载该页面的图片': [ 1346 | '下载该页面的图片', 1347 | 'ページの写真をダウンロードする', 1348 | 'Download the picture of the page', 1349 | '下載該頁面的圖片' 1350 | ], 1351 | '_下载该专辑的图片': [ 1352 | '下载该专辑的图片', 1353 | 'アルバムの画像をダウンロードする', 1354 | 'Download the album`s picture', 1355 | '下載該專輯的圖片' 1356 | ], 1357 | '_下载推荐图片': [ 1358 | '下载推荐图片', 1359 | 'おすすめ作品をダウンロードする', 1360 | 'Download recommended works', 1361 | '下載推薦圖片' 1362 | ], 1363 | '_下载推荐图片_title': [ 1364 | '下载为你推荐的图片', 1365 | 'あなたのお勧め作品をダウンロードする', 1366 | 'Download for your recommended works', 1367 | '下載為您推薦的圖片' 1368 | ], 1369 | '_下载相似图片': [ 1370 | '下载相似图片', 1371 | '類似の作品をダウンロードする', 1372 | 'Download similar works', 1373 | '下載相似圖片' 1374 | ], 1375 | '_要获取的作品个数': [ 1376 | '您想要获取多少个作品?(注意是个数而不是页数)\r\n请输入数字,最大值为', 1377 | 'いくつの作品をダウンロードしたいですか? (ページ数ではなく作品数に注意してください)\r\n数値を入力してください。最大値は', 1378 | 'How many works do you want to download? (Note that the number of works rather than the number of pages)\r\nPlease enter a number, max ', 1379 | '您想要取得多少個作品?(注意是個數而不是頁數)\r\n請輸入數字,最大值為' 1380 | ], 1381 | '_要获取的作品个数2': [ 1382 | '您想要获取多少个作品?', 1383 | 'いくつの作品をダウンロードしたいですか?', 1384 | 'How many works do you want to download?', 1385 | '您想要取得多少個作品?' 1386 | ], 1387 | '_数字提示1': [ 1388 | '-1, 或者大于 0', 1389 | '-1、または0より大きい', 1390 | '-1, or greater than 0', 1391 | '-1, 或是大於 0' 1392 | ], 1393 | '_超过最大值': [ 1394 | '您输入的数字超过了最大值', 1395 | '入力した番号が最大値を超えています', 1396 | 'The number you entered exceeds the maximum', 1397 | '您輸入的數字超過了最大值' 1398 | ], 1399 | '_下载大家的新作品': [ 1400 | '下载大家的新作品', 1401 | 'みんなの新作をダウンロードする', 1402 | 'Download everyone`s new work', 1403 | '下載大家的新作品' 1404 | ], 1405 | '_屏蔽设定': [ 1406 | '屏蔽設定', 1407 | 'ミュート設定', 1408 | 'Mute settings', 1409 | '封鎖設定' 1410 | ], 1411 | '_举报': [ 1412 | '举报', 1413 | '報告', 1414 | 'Report', 1415 | '回報' 1416 | ], 1417 | '_输入id进行下载': [ 1418 | '输入id进行下载', 1419 | 'IDでダウンロード', 1420 | 'Download by ID', 1421 | '輸入id進行下載' 1422 | ], 1423 | '_输入id进行下载的提示文字': [ 1424 | '请输入作品id。如果有多个id,则以换行分割(即每行一个id)', 1425 | 'イラストレーターIDを入力してください。 複数のidがある場合は、1行に1つのidを付けます。', 1426 | 'Please enter the illustration id. If there is more than one id, one id per line.', 1427 | '請輸入作品id。如果有多個id,則以換行分隔(即每行一個id)' 1428 | ], 1429 | '_开始下载': [ 1430 | '开始下载', 1431 | 'ダウンロードを開始する', 1432 | 'Start download', 1433 | '開始下載' 1434 | ], 1435 | '_开始抓取': [ 1436 | '开始抓取', 1437 | 'クロールを開始する', 1438 | 'Start crawling', 1439 | '開始擷取' 1440 | ], 1441 | '_添加tag': [ 1442 | '给未分类作品添加 tag', 1443 | '未分類の作品にタグを追加', 1444 | 'Add tag to unclassified work', 1445 | '給未分類作品添加 tag' 1446 | ], 1447 | '_id不合法': [ 1448 | 'id不合法,操作取消。', 1449 | 'idが不正な、操作はキャンセルされます。', 1450 | 'id is illegal, the operation is canceled.', 1451 | 'id不合法,動作取消。' 1452 | ], 1453 | '_快速收藏': [ 1454 | '快速收藏', 1455 | 'クイックブックマーク', 1456 | 'Quick bookmarks', 1457 | '快速收藏' 1458 | ], 1459 | '_显示': [ 1460 | '显示', 1461 | '表示', 1462 | 'display', 1463 | '顯示' 1464 | ], 1465 | '_是否显示封面': [ 1466 | '是否显示封面', 1467 | 'カバーを表示するかどうか', 1468 | 'Whether to display the cover', 1469 | '是否顯示封面' 1470 | ], 1471 | '_显示封面的提示': [ 1472 | '如果搜索结果数量很多,封面图数量也会很多。如果加载大量的封面图,会占用很多网络资源,也可能导致任务异常中断。如果遇到了这种情况,取消选中这个按钮。', 1473 | '検索結果の数が多い場合は、表紙画像の数が多くなります。 大量の表紙画像を読み込むと、ネットワークリソースが膨大になり、異常なタスクの中断を引き起こす可能性があります。 このような場合は、このボタンのチェックを外す。', 1474 | 'If the number of search results is large, the number of cover images will be many. If you load a large number of cover images, it will take up a lot of network resources, and it may cause abnormal interruption of tasks. If this happens, uncheck the button.', 1475 | '如果搜尋結果數量很多,封面圖數量也會很多。如果載入大量的封面圖,會占用很多網路資源,也可能導致工作異常中斷。如果遇到了這種情況,取消選取這個按鈕。' 1476 | ], 1477 | '_启用': [ 1478 | '启用', 1479 | '有効にする', 1480 | 'Enable', 1481 | '啟用' 1482 | ], 1483 | '_是否快速下载': [ 1484 | '是否快速下载', 1485 | 'すぐにダウンロードするかどうか', 1486 | 'Whether to download quickly', 1487 | '是否快速下載' 1488 | ], 1489 | '_快速下载的提示': [ 1490 | '当“开始下载”状态可用时,自动开始下载,不需要点击下载按钮。', 1491 | '「ダウンロードを開始する」ステータスが利用可能になると、ダウンロードは自動的に開始され、ダウンロードボタンをクリックする必要はありません。', 1492 | 'When the "Start Downloa" status is available, the download starts automatically and no need to click the download button.', 1493 | '當“開始下載”狀態可用時,自動開始下載,不需要點選下載按鈕。' 1494 | ], 1495 | '_是否下载XMP': [ 1496 | '是否创建XMP Sidecar', 1497 | 'Whether to create XMP sidecar file', 1498 | 'XMPコンパニオンファイルを作成するかどうか', 1499 | '是否創建XMP Sidecar' 1500 | ], 1501 | '_是否下载XMP的提示': [ 1502 | '创建保存Tag的XMP Sidecar文件。支持的软件包括:Adobe全家桶,Xnviewer', 1503 | 'Create XMP Sidecar file. Supply by: Adobe software, Xnviewer', 1504 | 'タグを保持するXMPサイドカーファイルを作成します。 サポートされているソフトウェアは次のとおりです。AdobeFamily Bar、Xnviewer', 1505 | '創建保存Tag的XMP Sidecar文件。支持的軟件包括:Adobe全家桶,Xnviewer' 1506 | ], 1507 | '_chrome72的提示': [ 1508 | 'XZPixivDownloader:\nChrome 的 72 版本会导致 Tampermonkey 的部分功能失效。如果您遇到了下载失败的情况,请将 Tampermonkey 升级到最新版(4.8 和以上)。\n此外,您也可以使用本工具的浏览器扩展版。(点击下载设置右上角的 Chrome 图标)', 1509 | 'XZPixivDownloader:\nChromeの72バージョンはTampermonkeyの機能のいくつかを無効にするでしょう。 ダウンロードに失敗した場合は、Tampermonkeyを最新バージョン(4.8以上)にアップグレードしてください。 \nまた、このツールのブラウザ拡張機能も使用できます。 (ダウンロード設定の右上にあるChromeアイコンをクリックしてください)', 1510 | `XZPixivDownloader:\nThe 72 version of Chrome will disable some of Tampermonkey's features. If you are experiencing a download failure, upgrade Tampermonkey to the latest version (4.8 and above). \nIn addition, you can also use the browser extension of this tool. (Click the Chrome icon in the top right corner of the download settings)`, 1511 | 'XZPixivDownloader:\nChrome 的 72 版本會導致 Tampermonkey 的部分功能失效。如果您遇到了下載失敗的情況,請將 Tampermonkey 升級到最新版(4.8 和以上)。\n此外,您也可以使用本工具的瀏覽器擴展版。 (點擊下載設置右上角的 Chrome 圖標)' 1512 | ] 1513 | }; 1514 | 1515 | // xianzun_lang_translate 翻译 1516 | function xzlt (name, ...arg) { 1517 | let content = xz_lang[name][lang_type]; 1518 | arg.forEach(val => content = content.replace('{}', val)); 1519 | return content; 1520 | } 1521 | 1522 | // 检测脚本版因 Chrome 72 导致不能正常下载的情况 1523 | let tip_chrome72 = localStorage.getItem('tip_chrome72'); 1524 | if (!tip_chrome72) { 1525 | let chrome_ver = /Chrome\/(.*)? /.exec(navigator.userAgent); 1526 | if (chrome_ver) { 1527 | chrome_ver = chrome_ver[1]; // 例如 '72.0.3626.109' 1528 | } 1529 | let GM_ver = GM_info.version; // 例如 '4.8' 1530 | if (chrome_ver >= '72' && GM_ver < '4.8') { 1531 | alert(xzlt('_chrome72的提示')); 1532 | localStorage.setItem('tip_chrome72', 1); 1533 | } 1534 | } 1535 | 1536 | // 添加 css 样式 1537 | styleE = document.createElement('style'); 1538 | document.body.appendChild(styleE); 1539 | styleE.textContent = `#header-banner.ad,._1N-LC6t,._2vNejsc,._3M6FtEB,._3jgsYyw,._premium-lead-promotion-banner,._premium-lead-tag-search-bar,.ad-bigbanner,.ad-footer,.ad-multiple_illust_viewer,.ads_anchor,.ads_area,.adsbygoogle,.popular-introduction-overlay,.ui-fixed-container aside,[name=header],section.ad{display:none!important;z-index:-999!important;width:0!important;height:0!important;opacity:0!important}#viewerWarpper{margin:24px auto 15px;overflow:hidden;background:#fff;padding:0 16px 68px;display:none;border-top:1px solid #eee;border-bottom:1px solid #eee}#viewerWarpper ul{max-width:568px;margin:24px auto;padding:0 16px 48px;display:flex;justify-content:flex-start;align-items:center;flex-wrap:nowrap;overflow:auto}#viewerWarpper li{display:flex;flex-shrink:0;margin-right:8px;overflow:hidden}#viewerWarpper li img{cursor:pointer;max-height:144px;width:auto}.viewer-toolbar .viewer-next,.viewer-toolbar .viewer-prev{background-color:rgba(0,0,0,.8);border-radius:50%;cursor:pointer;height:100px;width:100px;overflow:hidden}.viewer-backdrop{background:rgba(0,0,0,.8)}.viewer-toolbar .viewer-prev{position:fixed;left:-70px;top:40%}.viewer-toolbar .viewer-prev::before{top:40px;left:70px;position:absolute}.viewer-toolbar .viewer-next{position:fixed;right:-70px;top:40%}#quick_down_btn,#rightButton{line-height:20px;border-radius:3px;color:#fff;padding:10px;box-sizing:content-box;right:0;text-align:center;cursor:pointer}.viewer-toolbar .viewer-next::before{left:10px;top:40px;position:absolute}#quick_down_btn,#rightButton,.centerWrap{position:fixed;z-index:5000;font-size:14px}.black-background{background:rgba(0,0,0,1)}#rightButton{top:15%;background:#80b9f7}#quick_down_btn{top:20%;background:#0096fa}li{list-style:none}.centerWrap{display:none;width:650px;left:-350px;margin-left:50%;background:#fff;top:3%;z-index:5000;color:#333;padding:25px;border-radius:15px;border:1px solid #ddd;box-shadow:0 0 25px #2ca6df;max-height: calc(94% - 50px);overflow: auto;}.centerWrap p{line-height:24px;margin:0}.centerWrap .tip{color:#999}.centerWrap_head{height:30px;position:relative;padding-bottom:10px}.centerWrap_head *{vertical-align:middle}.centerWrap_title{display:block;line-height:30px;text-align:center;font-size:18px}.centerWrap_close,.centerWrap_toogle_option,.chrome_extension,.firefox_extension,.github_url{font-size:18px;position:absolute;top:0;right:0;width:30px;height:30px;text-align:center;cursor:pointer;color:#666;user-select:none}.download_progress1,.right1{position:relative}.centerWrap_close:hover,.centerWrap_toogle_option:hover{color:#0096fa}.centerWrap_toogle_option{right:40px}.chrome_extension,.firefox_extension{display:block;right:80px;text-decoration:none}.github_url{display:block;right:120px}.centerWrap_head img{max-width:100%;width:16px}.setinput_style1{width:50px;min-width:50px;line-height:20px;font-size:14px!important;height:20px;text-indent:4px;box-sizing:border-box;border:none!important;border-bottom:1px solid #999!important;outline:0}.progressBar1,.right1{width:500px}.setinput_style1:focus{border-bottom:1px solid #0096fa!important;background:0 0!important}.fileNameRule,.folderNameRule{min-width:150px}.setinput_tag{min-width:300px}.how_to_create_folder,.showFileNameResult,.showFileNameTip,.showFolderNameTip{cursor:pointer}.fileNameTip,.folderNameTip{display:none;padding-top:5px}.centerWrap_btns{padding:10px 0 0;font-size:0}.XZTipEl,.centerWrap_btns div,.progressTip{color:#fff;font-size:14px}.centerWrap_btns div{display:inline-block;min-width:100px;max-width:105px;padding:8px 10px;text-align:center;min-height:20px;line-height:20px;border-radius:4px;margin-right:35px;cursor:pointer;margin-bottom:10px;vertical-align:top}.progress,.progressBar{border-radius:11px;height:22px}.centerWrap_btns_free div{max-width:140px;margin-right:15px}.centerWrap_down_tips{line-height:28px}.right1{display:inline-block;height:22px;vertical-align:middle}.progressBar{position:absolute;background:#6792A2}.progress{background:#0eb3f3;transition:.15s}.progressTip{position:absolute;line-height:22px}.progress1{width:0}.progressTip1{width:500px;text-align:center}.centerWrap_down_list{display:none}.centerWrap_down_list ul{padding-top:5px;margin:0;padding-left:0}.downloadBar{position:relative;width:100%;padding:5px 0;height:22px;box-sizing:content-box}.progressBar2{width:100%}.progress2{width:0}.progressTip2{width:100%}.download_fileName{max-width:60%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;vertical-align:top;display:inline-block;text-indent:1em}.showDownTip{padding-top:10px;cursor:pointer;display:inline-block}.XZTipEl,.downTip,.download_a,.download_panel{display:none}.settingNameStyle1{width:100px;cursor:pointer;margin-right:10px}.XZTipEl{position:fixed;z-index:5001;max-width:400px;left:0;top:0;background:#02a3ec;padding:6px 8px;border-radius:5px;line-height:20px;word-break:break-word}.fwb{font-weight:700}.gray1{color:#999}.xz_blue{color:#0ea8ef!important}.outputInfoWrap{padding:20px 30px;width:520px;background:#fff;border-radius:20px;z-index:9999;box-shadow:0 0 15px #2ca6df;display:none;position:fixed;top:15%;margin-left:-300px;left:50%}.outputUrlTitle{height:20px;line-height:20px;text-align:center;font-size:18px;color:#179FDD}.outputInfoContent{border:1px solid #ccc;transition:.3s;font-size:14px;margin-top:10px;padding:5px 10px;overflow:auto;max-height:350px;line-height:20px}.outputInfoContent::selection{background:#179FDD;color:#fff}.outputUrlFooter{height:60px;text-align:center}.outputUrlClose{cursor:pointer;position:absolute;width:30px;height:30px;top:20px;right:30px;z-index:9999;font-size:18px;text-align:center}.outputUrlClose:hover{color:#179FDD}.outputUrlCopy{height:34px;line-height:34px;min-width:100px;padding:2px 25px;margin-top:15px;background:#179FDD;display:inline-block;color:#fff;font-size:14px;border-radius:6px;cursor:pointer}#down_id_input,#outputInfo{margin:6px auto;background:#fff}.fastScreenArea a{display:inline-block;padding:10px}#quickBookmarkEl{font-size:34px;line-height:30px;margin-right:15px;cursor:pointer;color:#333;text-decoration:none;display:block}#outputInfo{padding:10px;font-size:14px;width:950px}#down_id_input{width:600px;height:80px;font-size:12px;padding:7px;display:none;border:1px solid #179FDD}.sc-cLxPOX{padding-top:0}@keyframes exTip{0%{opacity:1}100%{opacity:0}}.extension_tip{animation:exTip 0.2s linear 0s infinite alternate forwards;filter: invert(58%) sepia(77%) saturate(2661%) hue-rotate(165deg) brightness(95%) contrast(97%);}`; 1540 | 1541 | // 创建输出抓取进度的区域 1542 | let outputInfo = document.createElement('div'); 1543 | outputInfo.id = 'outputInfo'; 1544 | 1545 | // 快速收藏 1546 | function quickBookmark () { 1547 | // 本函数一直运行。因为切换作品(pushstate)时,不能准确的知道 toolbar 何时更新,所以只能不断检测,这样在切换作品时才不会出问题 1548 | setTimeout(() => { 1549 | quickBookmark(); 1550 | }, 300); 1551 | 1552 | let toolbar; // 因为 p 站改版 class 经常变,所以从父元素查找,父元素的 class 变化没那么频繁. main 元素 1553 | let toolbar_parent = document.querySelectorAll('main > section'); 1554 | for (const el of toolbar_parent) { 1555 | if (el.querySelector('div>section')) { 1556 | toolbar = el.querySelector('div>section'); 1557 | break; 1558 | } 1559 | } 1560 | 1561 | if (toolbar) { 1562 | quickBookmarkElement = document.querySelector(`#quickBookmarkEl`); 1563 | if (!quickBookmarkElement) { // 如果没有 quick 元素则添加 1564 | // 创建快速收藏元素 1565 | quickBookmarkElement = document.createElement('a'); 1566 | quickBookmarkElement.id = 'quickBookmarkEl'; 1567 | quickBookmarkElement.innerHTML = '✩'; 1568 | quickBookmarkElement.href = 'javascript:void(0)'; 1569 | quickBookmarkElement.title = xzlt('_快速收藏'); 1570 | toolbar.insertBefore(quickBookmarkElement, toolbar.childNodes[3]); 1571 | // 隐藏原来的收藏按钮并检测收藏状态 1572 | toolbar.childNodes[2].style.display = 'none'; 1573 | let heart = toolbar.childNodes[2].querySelector('svg'); 1574 | if (getComputedStyle(heart)['fill'] === 'rgb(255, 64, 96)') { // 如果已经收藏过了 1575 | quickBookmarkEnd(); 1576 | } else { 1577 | quickBookmarkElement.addEventListener('click', () => { 1578 | // 自动点赞 1579 | document.querySelector('._35vRH4a').click(); 1580 | // 储存 tag 1581 | let tagElements = document.querySelectorAll('._1LEXQ_3 li'); 1582 | let tagArray = Array.from(tagElements).map(el => { 1583 | let now_a = el.querySelector('a'); 1584 | if (now_a) { 1585 | return now_a.textContent; // 储存 tag 1586 | } 1587 | }); 1588 | // 对于原创作品,非日文的页面上只显示了用户语言的“原创”,替换成日文 tag “オリジナル”。 1589 | if (tagArray[0] === '原创' || tagArray[0] === 'Original' || tagArray[0] === '창작') { 1590 | tagArray[0] = 'オリジナル'; 1591 | } else if (tagArray[1] === '原创' || tagArray[1] === 'Original' || tagArray[1] === '창작') { 1592 | tagArray[1] = 'オリジナル'; 1593 | } 1594 | let tagString = encodeURI(tagArray.join(' ')); 1595 | let tt = getToken(); 1596 | // 调用添加收藏的 api 1597 | addBookmark(getIllustId(), tagString, tt) 1598 | .then(response => response.json()) 1599 | .then(data => { 1600 | if (data.error !== undefined && data.error === false) { 1601 | quickBookmarkEnd(); 1602 | } 1603 | }); 1604 | }); 1605 | } 1606 | } else { // 如果有 quick 元素,什么都不做 1607 | return false; 1608 | } 1609 | } 1610 | } 1611 | 1612 | // 如果这个作品已收藏 1613 | function quickBookmarkEnd () { 1614 | quickBookmarkElement.style.color = '#FF4060'; 1615 | quickBookmarkElement.href = `/bookmark_add.php?type=illust&illust_id=${getIllustId()}`; 1616 | } 1617 | // 获取 token 1618 | function getToken () { 1619 | if (unsafeWindow.globalInitData) { 1620 | return unsafeWindow.globalInitData.token; 1621 | } 1622 | if (document.querySelector('input[name="tt"]')) { 1623 | return document.querySelector('input[name="tt"]').value; 1624 | } 1625 | return false; 1626 | } 1627 | 1628 | // 添加收藏 1629 | function addBookmark (id, tags, tt, hide) { 1630 | if (!hide) { // 公开作品 1631 | hide = 0; 1632 | } else { // 非公开作品 1633 | hide = 1; 1634 | } 1635 | return fetch('https://www.pixiv.net/rpc/index.php', { 1636 | method: 'post', 1637 | headers: { 1638 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 1639 | }, 1640 | credentials: 'include', // 附带 cookie 1641 | body: `mode=save_illust_bookmark&illust_id=${id}&restrict=${hide}&comment=&tags=${tags}&tt=${tt}` 1642 | }); 1643 | } 1644 | 1645 | // 准备添加 tag 1646 | async function readyAddTag () { 1647 | let add_list = []; // 需要添加的作品列表 1648 | let index = 0; 1649 | let add_tag_btn = document.getElementById('add_tag_btn'); 1650 | // 公开的未分类收藏 1651 | let api1 = `https://www.pixiv.net/ajax/user/${getUserId()}/illusts/bookmarks?tag=${encodeURI('未分類')}&offset=0&limit=999999&rest=show&rdm=${Math.random()}`; 1652 | // 非公开的未分类收藏 1653 | let api2 = `https://www.pixiv.net/ajax/user/${getUserId()}/illusts/bookmarks?tag=${encodeURI('未分類')}&offset=0&limit=999999&rest=hide&rdm=${Math.random()}`; 1654 | add_list = add_list.concat(await getInfoFromBookmark(api1)); 1655 | add_list = add_list.concat(await getInfoFromBookmark(api2)); 1656 | if (add_list.length === 0) { 1657 | add_tag_btn.textContent = `√ no need`; 1658 | return false; 1659 | } else { 1660 | addTag(index, add_list, getToken(), add_tag_btn); 1661 | } 1662 | } 1663 | 1664 | // 从收藏的作品里获取信息,每个作品返回 id 和 tag 信息 1665 | function getInfoFromBookmark (url) { 1666 | return fetch(url, { 1667 | credentials: "same-origin" 1668 | }) 1669 | .then(response => { 1670 | if (response.ok) { 1671 | return response.json(); 1672 | } else { 1673 | if (response.status === 403) { 1674 | console.log('permission denied'); 1675 | document.getElementById('add_tag_btn').textContent = `× permission denied`; 1676 | } 1677 | return Promise.reject({ 1678 | status: response.status, 1679 | statusText: response.statusText 1680 | }); 1681 | } 1682 | }) 1683 | .then(data => { 1684 | let works = data.body.works; 1685 | let result = []; 1686 | if (works.length >= 1 && works[0].bookmarkData) { // 判断了作品的 bookmarkData,如果为假说明这是在别人的收藏页面,不再获取数据。 1687 | works.forEach(data => { 1688 | 1689 | result.push({ 1690 | 'id': data.id, 1691 | 'tags': encodeURI(data.tags.join(' ')), 1692 | 'restrict': data.bookmarkData.private 1693 | }); 1694 | }); 1695 | } 1696 | return result; 1697 | }); 1698 | } 1699 | 1700 | // 添加 tag 1701 | function addTag (index, add_list, tt, add_tag_btn) { 1702 | setTimeout(() => { 1703 | if (index < add_list.length) { 1704 | addBookmark(add_list[index].id, add_list[index].tags, tt, add_list[index].restrict); 1705 | index++; 1706 | add_tag_btn.textContent = `${index} / ${add_list.length}`; 1707 | addTag(index, add_list, tt, add_tag_btn); 1708 | } else { 1709 | add_tag_btn.textContent = `√ complete`; 1710 | } 1711 | }, 100); 1712 | } 1713 | 1714 | // 初始化动图 1715 | function initGIF () { 1716 | // 切换作品时,重置动图信息 1717 | gif_src = ''; 1718 | gif_delay = undefined; 1719 | gif_mime_type = ''; 1720 | zip_file = null; // 获取的 zip 文件 1721 | file_number = undefined; // 动图压缩包里有多少个文件 1722 | gif_img_list.innerHTML = ''; // 清空图片列表 1723 | download_gif_btn.style.display = 'inline-block'; // 显示动图转换按钮 1724 | // 获取 gif 信息 1725 | fetch('https://www.pixiv.net/ajax/illust/' + getIllustId() + '/ugoira_meta', { 1726 | method: 'get', 1727 | credentials: 'include', // 附带 cookie 1728 | }) 1729 | .then(response => response.json()) 1730 | .then(data => { 1731 | let this_one_data = data.body; 1732 | gif_src = this_one_data.originalSrc; 1733 | file_number = this_one_data.frames.length; 1734 | gif_delay = this_one_data.frames[0].delay; 1735 | gif_mime_type = this_one_data.mime_type; 1736 | }); 1737 | 1738 | if (!convert_lib_loaded) { 1739 | loadGifJS(); 1740 | } 1741 | } 1742 | 1743 | // 加载转换所需文件 1744 | function loadGifJS () { 1745 | let url = gif_js_urls.shift(); 1746 | let filename = /.*\/(.*)\./.exec(url)[1]; 1747 | fetch(url) 1748 | .then(res => res.blob()) 1749 | .then(data => { 1750 | let blob_url = URL.createObjectURL(data); 1751 | convert_lib_urls[filename] = blob_url; 1752 | if (filename === 'zip' || filename === 'gif') { 1753 | let el = document.createElement('script'); 1754 | el.setAttribute('type', 'text/javascript'); 1755 | el.setAttribute('src', blob_url); 1756 | document.head.appendChild(el); 1757 | } 1758 | if (gif_js_urls.length === 0) { 1759 | convert_lib_loaded = true; 1760 | } else { 1761 | loadGifJS(); 1762 | } 1763 | }); 1764 | } 1765 | 1766 | // 检查是否可以转换 gif 1767 | function checkCanConvert () { 1768 | clearInterval(check_convert_timer); 1769 | // 如果库文件未加载完成,或者未获取到 gif 信息,或者 zip 文件未加载完成,过一会儿再检查 1770 | if (!convert_lib_loaded || !gif_src || !zip_file) { 1771 | setTimeout(() => { 1772 | checkCanConvert(); 1773 | }, 1000); 1774 | return false; 1775 | } else { 1776 | startconvert(); 1777 | } 1778 | } 1779 | 1780 | // 开始转换 1781 | function startconvert () { 1782 | addOutputInfo('
' + xzlt('_转换中请等待')); 1783 | zip.workerScripts = { 1784 | inflater: [convert_lib_urls['z-worker'], convert_lib_urls['inflate']] 1785 | }; 1786 | readZip(); 1787 | } 1788 | 1789 | // 读取 zip 文件 1790 | function readZip () { 1791 | zip.createReader(new zip.BlobReader(zip_file), zipReader => { 1792 | // 读取成功时的回调函数,files 为文件列表 1793 | zipReader.getEntries(files => { 1794 | file_number = files.length; 1795 | files.forEach(file => { 1796 | // 获取每个文件的数据,在 BlobWriter 里设置 mime type,回调函数返回 blob 数据 1797 | file.getData(new zip.BlobWriter(gif_mime_type), data => addImgList(URL.createObjectURL(data))); 1798 | }); 1799 | }); 1800 | }, message => { 1801 | console.log('readZIP error: ' + message); 1802 | addOutputInfo('error: convert to gif failed.'); 1803 | }); 1804 | } 1805 | 1806 | // 输出图片列表 1807 | function addImgList (url) { 1808 | let new_img = new Image(); 1809 | new_img.onload = () => { 1810 | file_number--; 1811 | if (file_number == 0) { // 所有图片都加载完成后 1812 | renderGIF(); 1813 | } 1814 | }; 1815 | new_img.src = url; 1816 | gif_img_list.appendChild(new_img); 1817 | } 1818 | 1819 | // 渲染 gif 1820 | function renderGIF () { 1821 | console.log('renderGIF'); 1822 | // 配置 gif.js 1823 | var gif = new GIF({ 1824 | workers: 4, // 如果 workers 大于1,合成的 gif 有可能会抖动 1825 | quality: 10, 1826 | workerScript: convert_lib_urls['gif.worker'] 1827 | }); 1828 | 1829 | // 添加图片 1830 | let imgs = gif_img_list.querySelectorAll('img'); 1831 | imgs.forEach(element => { 1832 | gif.addFrame(element, { 1833 | delay: gif_delay 1834 | }); 1835 | }); 1836 | console.time('gif'); 1837 | // 渲染完成事件 1838 | gif.on('finished', blob => { 1839 | console.timeEnd('gif'); // 显示渲染用了多久 1840 | download_a = document.querySelector('.download_a'); 1841 | download_a.href = URL.createObjectURL(blob); 1842 | download_a.setAttribute('download', getIllustId() + '.gif'); 1843 | download_a.click(); 1844 | changeTitle('√'); 1845 | addOutputInfo('
' + xzlt('_转换完成')); 1846 | }); 1847 | 1848 | // 开始渲染 1849 | gif.render(); 1850 | } 1851 | 1852 | // 初始化图片查看器 1853 | function initViewer () { 1854 | if (!viewer_enable) { 1855 | return false; 1856 | } 1857 | if (typeof Viewer !== 'function') { 1858 | loadViewer(); 1859 | return false; 1860 | } 1861 | if (!document.getElementById('viewerWarpper')) { 1862 | createViewer(); 1863 | return false; 1864 | } 1865 | if (document.getElementById('viewerWarpper')) { // 每次被调用时,如果一切都准备好了,则更新数据 1866 | updateViewer(); 1867 | } 1868 | } 1869 | 1870 | // 加载图片查看器 js 文件 1871 | function loadViewer () { 1872 | fetch('https://greasyfork.org/scripts/369647-viewer-js-mix/code/Viewerjs%20mix.js', { 1873 | method: 'get' 1874 | }) 1875 | .then(response => response.text()) 1876 | .then(data => { 1877 | let element = document.createElement('script'); 1878 | element.setAttribute('type', 'text/javascript'); 1879 | element.innerHTML = data; 1880 | document.head.appendChild(element); 1881 | if (typeof Viewer === 'function') { 1882 | initViewer(); 1883 | } 1884 | }); 1885 | } 1886 | 1887 | // 创建图片查看器 html 元素,并绑定一些事件 1888 | function createViewer () { 1889 | if (!document.querySelector('main figcaption')) { // 如果图片中间部分的元素还未生成,则过一会儿再检测 1890 | setTimeout(() => { 1891 | createViewer(); 1892 | }, 200); 1893 | return false; 1894 | } 1895 | 1896 | // 图片列表 html 结构: div#viewerWarpper > ul > li > img 1897 | viewerWarpper = document.createElement('div'); 1898 | viewerWarpper.id = 'viewerWarpper'; 1899 | viewerUl = document.createElement('ul'); 1900 | viewerWarpper.appendChild(viewerUl); 1901 | document.querySelector('main figcaption').insertAdjacentElement('beforebegin', viewerWarpper); 1902 | 1903 | // 图片查看器显示之后 1904 | viewerUl.addEventListener('shown', () => { 1905 | // 显示相关元素 1906 | showViewerOther(); 1907 | // 绑定点击全屏事件 1908 | document.querySelector('.viewer-one-to-one').addEventListener('click', () => { 1909 | hideViewerOther(); // 隐藏查看器的其他元素 1910 | launchFullScreen(document.body); // 进入全屏 1911 | setTimeout(() => { // 使图片居中显示,必须加延迟 1912 | setViewerCenter(); 1913 | }, 100); 1914 | }); 1915 | }); 1916 | 1917 | // 全屏状态下,查看器查看和切换图片时,始终显示为100% 1918 | viewerUl.addEventListener('view', () => { 1919 | if (isFullscreen()) { 1920 | setTimeout(() => { // 通过点击 1:1 按钮,调整为100%并居中。这里必须要加延时,否则点击的时候图片还是旧的 1921 | document.querySelector('.viewer-one-to-one').click(); 1922 | }, 50); 1923 | } 1924 | }); 1925 | 1926 | // 查看器隐藏时,如果还处于全屏,则退出全屏 1927 | viewerUl.addEventListener('hidden', () => { 1928 | if (isFullscreen()) { 1929 | exitFullscreen(); 1930 | } 1931 | }); 1932 | 1933 | // esc 退出图片查看器 1934 | document.addEventListener('keyup', event => { 1935 | let e = event || window.event; 1936 | if (e.keyCode == 27) { // 按下 esc 1937 | // 如果非全屏,且查看器已经打开,则退出查看器 1938 | if (!isFullscreen() && viewerIsShow()) { 1939 | document.querySelector('.viewer-close').click(); 1940 | } 1941 | } 1942 | }); 1943 | 1944 | updateViewer(); 1945 | } 1946 | 1947 | // 根据作品信息处理 1948 | function updateViewer () { 1949 | viewerWarpper.style.display = 'none'; // 先隐藏 viewerWarpper 1950 | // 获取作品信息 1951 | fetch('https://www.pixiv.net/ajax/illust/' + getIllustId(), { 1952 | method: 'get', 1953 | credentials: 'include', // 附带 cookie 1954 | }) 1955 | .then(response => response.json()) 1956 | .then(data => { 1957 | let this_one_data = data.body; 1958 | // 处理 图片查看器 1959 | if (this_one_data.illustType === 0 || this_one_data.illustType === 1) { // 单图或多图,0插画1漫画2动图(1的如68430279) 1960 | if (this_one_data.pageCount > 1) { // 多图 1961 | // 当作品类型为 插画或者漫画,并且是多图时,才会产生缩略图 1962 | let { 1963 | thumb, 1964 | original 1965 | } = this_one_data.urls; 1966 | // https://i.pximg.net/c/240x240/img-master/img/2017/11/28/00/23/44/66070515_p0_master1200.jpg 1967 | // https://i.pximg.net/img-original/img/2017/11/28/00/23/44/66070515_p0.png 1968 | viewerUl.innerHTML = new Array(parseInt(this_one_data.pageCount)).fill(1).reduce((html, now, index) => { 1969 | return html += `
  • `; 1970 | }, ''); 1971 | // 数据更新后,显示 viewerWarpper 1972 | viewerWarpper.style.display = 'block'; 1973 | // 销毁看图组件 1974 | if (myViewer) { 1975 | myViewer.destroy(); 1976 | } 1977 | // 重新配置看图组件 1978 | myViewer = new Viewer(viewerUl, { 1979 | toolbar: { 1980 | zoomIn: 0, 1981 | zoomOut: 0, 1982 | oneToOne: 1, 1983 | reset: 0, 1984 | prev: 1, 1985 | play: { 1986 | show: 0, 1987 | size: 'large', 1988 | }, 1989 | next: 1, 1990 | rotateLeft: 0, 1991 | rotateRight: 0, 1992 | flipHorizontal: 0, 1993 | flipVertical: 0, 1994 | }, 1995 | url (image) { 1996 | return image.getAttribute('data-src'); 1997 | }, 1998 | viewed (event) { // 当图片显示完成(加载完成)后,预加载下一张图片 1999 | let ev = event || window.event; 2000 | let index = ev.detail.index; 2001 | if (index < this_one_data.pageCount - 1) { 2002 | index++; 2003 | } 2004 | let next_img = original.replace('p0', 'p' + index); 2005 | let img = new Image(); 2006 | img.src = next_img; 2007 | }, 2008 | transition: false, // 取消一些动画,比如切换图片时,图片从小变大出现的动画 2009 | keyboard: false, // 取消键盘支持,主要是用键盘左右方向键切换的话,会和 pixiv 页面产生冲突。(pixiv 页面上,左右方向键会切换作品) 2010 | title: false, // 不显示 title(图片名和宽高信息) 2011 | tooltip: false, // 不显示缩放比例 2012 | }); 2013 | // 预加载第一张图片 2014 | { 2015 | let img = new Image(); 2016 | img.src = original; 2017 | } 2018 | } 2019 | } 2020 | }); 2021 | } 2022 | 2023 | // 隐藏查看器的其他元素 2024 | function hideViewerOther () { 2025 | document.querySelector('.viewer-container').classList.add('black-background'); 2026 | document.querySelector('.viewer-close').style.display = 'none'; 2027 | // 隐藏底部的其他元素,仍然显示左右切换按钮 2028 | document.querySelector('.viewer-one-to-one').style.display = 'none'; 2029 | document.querySelector('.viewer-navbar').style.display = 'none'; 2030 | } 2031 | 2032 | // 显示查看器的其他元素 2033 | function showViewerOther () { 2034 | document.querySelector('.viewer-container').classList.remove('black-background'); 2035 | document.querySelector('.viewer-close').style.display = 'block'; 2036 | document.querySelector('.viewer-one-to-one').style.display = 'block'; 2037 | document.querySelector('.viewer-navbar').style.display = 'block'; 2038 | } 2039 | 2040 | // 在图片100%显示时,使其居中 2041 | function setViewerCenter () { 2042 | // 获取图片宽高 2043 | let imgInfo = document.querySelector('.viewer-title').textContent; 2044 | if (!imgInfo) { // 但是如果图片尚未加载出来的话,就没有内容,就过一会儿再执行 2045 | setTimeout(() => { 2046 | setViewerCenter(); 2047 | }, 200); 2048 | return false; 2049 | } 2050 | let [imgWidth, imgHeight] = /\d{1,5} × \d{1,5}/.exec(imgInfo)[0].split(' × '); 2051 | // > '66360324_p5_master1200.jpg (919 × 1300)' 2052 | // < ["919", "1300"] 2053 | myViewer.zoomTo(1); 2054 | // 获取网页宽高 2055 | let htmlWidth = document.documentElement.clientWidth; 2056 | let htmlHeight = document.documentElement.clientHeight; 2057 | // 设置边距 2058 | let setWidth = (htmlWidth - imgWidth) / 2; 2059 | let setHeight = (htmlHeight - imgHeight) / 2; 2060 | if (setHeight < 0) { // 当图片高度大于浏览器窗口高度时,居顶显示而不是居中 2061 | setHeight = 0; 2062 | } 2063 | myViewer.moveTo(setWidth, setHeight); 2064 | } 2065 | 2066 | // 进入全屏 2067 | function launchFullScreen (element) { 2068 | if (element.requestFullscreen) { 2069 | element.requestFullscreen(); 2070 | } else if (element.msRequestFullscreen) { 2071 | element.msRequestFullscreen(); 2072 | } else if (element.mozRequestFullScreen) { 2073 | element.mozRequestFullScreen(); 2074 | } else if (element.webkitRequestFullscreen) { 2075 | element.webkitRequestFullscreen(); 2076 | } 2077 | } 2078 | 2079 | // 退出全屏 2080 | function exitFullscreen () { 2081 | if (document.exitFullscreen) { 2082 | document.exitFullscreen(); 2083 | } else if (document.mozExitFullScreen) { 2084 | document.mozExitFullScreen(); 2085 | } else if (document.webkitExitFullscreen) { 2086 | document.webkitExitFullscreen(); 2087 | } 2088 | } 2089 | 2090 | // 判断是否处于全屏状态 2091 | function isFullscreen () { 2092 | return document.fullscreenElement || document.msFullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || false; 2093 | } 2094 | 2095 | // 判断看图器是否显示 2096 | function viewerIsShow () { 2097 | let viewer_container = document.querySelector('.viewer-container'); 2098 | if (viewer_container) { 2099 | return viewer_container.classList.contains('viewer-in'); 2100 | } else { 2101 | return false; 2102 | } 2103 | } 2104 | 2105 | // 检测全屏状态变化,目前有兼容性问题(这里也相当于绑定了按 esc 退出的事件) 2106 | ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange'].forEach(arg => { 2107 | document.addEventListener(arg, () => { 2108 | if (!isFullscreen()) { // 退出全屏 2109 | showViewerOther(); 2110 | } 2111 | }); 2112 | }); 2113 | 2114 | // 修改title 2115 | function changeTitle (string) { 2116 | // 本工具的提醒会以 [string] 形式添加到 title 最前面 2117 | /* 2118 | 0 复原 2119 | ↑ 抓取中 2120 | → 等待下一步操作(tag搜索页) 2121 | ▶ 准备下载 2122 | ↓ 下载中 2123 | ║ 下载暂停 2124 | ■ 下载停止 2125 | √ 下载完毕 2126 | */ 2127 | if (string === '0') { 2128 | clearInterval(title_timer); 2129 | document.title = old_title; 2130 | return false; 2131 | } 2132 | if (document.title[0] !== '[') { // 如果当前title里没有本脚本的提醒,就存储当前title为旧title 2133 | old_title = document.title; 2134 | } 2135 | let new_title = `[${string}] ${old_title}`; 2136 | document.title = new_title; 2137 | // 当可以执行下一步操作时,闪烁提醒 2138 | if (string === '▶' || string === '→') { 2139 | title_timer = setInterval(function () { 2140 | if (document.title.includes(string)) { 2141 | document.title = new_title.replace(string, ' '); 2142 | } else { 2143 | document.title = new_title; 2144 | } 2145 | }, 500); 2146 | } else { 2147 | clearInterval(title_timer); 2148 | } 2149 | } 2150 | 2151 | // 添加输出区域 2152 | function insertOutputInfo () { 2153 | if (document.getElementById('outputInfo') === null) { 2154 | insertToHead(outputInfo); 2155 | } 2156 | } 2157 | 2158 | // 增加输出信息 2159 | function addOutputInfo (val) { 2160 | outputInfo.innerHTML += val; 2161 | } 2162 | 2163 | // 获取排除类型 2164 | function getNotDownType () { 2165 | return Array.from(document.body.querySelectorAll('.XZFormP5 input')).reduce((result, el, index) => { 2166 | if (el.checked === false) { 2167 | return result += (index + 1); 2168 | } else { 2169 | return result; 2170 | } 2171 | }, ''); 2172 | } 2173 | 2174 | // 检查排除作品类型的参数是否合法 2175 | function checkNotDownType () { 2176 | notdown_type = getNotDownType(); 2177 | // 如果全部排除则取消任务 2178 | if (notdown_type.includes('123')) { // notdown_type 的结果是顺序的,所以可以直接查找 123 2179 | alert(xzlt('_check_notdown_type_result1_弹窗')); 2180 | addOutputInfo('
    ' + xzlt('_check_notdown_type_result1_html') + '

    '); 2181 | return false; 2182 | } 2183 | // 排除了至少一种时,显示提示 2184 | if (notdown_type.includes('1') || notdown_type.includes('2') || notdown_type.includes('3')) { 2185 | addOutputInfo('
    ' + xzlt('_check_notdown_type_result3_html') + notdown_type.replace('1', xzlt('_单图')).replace('2', xzlt('_多图')).replace('3', xzlt('_动图'))); 2186 | } 2187 | } 2188 | 2189 | // 检查作品是否符合过滤类型。所有添加了setNotDownType按钮的都要到这里检查一遍 2190 | function checkNotDownType_result (string, url, bookmarked) { 2191 | // 如果设置了只下载书签作品 2192 | if (only_down_bmk) { 2193 | if (!bookmarked) { 2194 | return false; 2195 | } 2196 | } 2197 | 2198 | if (string.includes('multiple')) { //如果是多图并且没有排除多图 2199 | if (!notdown_type.includes('2')) { 2200 | illust_url_list.push(url); 2201 | } 2202 | } else if (string.includes('ugoku-illust')) { //如果是动图并且没有排除动图 2203 | if (!notdown_type.includes('3')) { 2204 | illust_url_list.push(url); 2205 | } 2206 | } else { //如果是单图并且没有排除单图(包括mode=big) 2207 | if (!notdown_type.includes('1')) { 2208 | illust_url_list.push(url); 2209 | } 2210 | } 2211 | } 2212 | 2213 | // 检查是否设置了多图作品的张数限制 2214 | function check_multiple_down_number () { 2215 | let check_result = checkNumberGreater0(XZForm.setPNo.value); 2216 | if (check_result) { 2217 | multiple_down_number = check_result.value; 2218 | addOutputInfo('
    ' + xzlt('_多图作品下载张数', multiple_down_number)); 2219 | } else { 2220 | multiple_down_number = 0; 2221 | } 2222 | } 2223 | 2224 | // 插入到页面顶部,大部分页面使用 header,文章页使用 root。因为在文章页执行脚本时,可能获取不到 header 2225 | function insertToHead (el) { 2226 | (document.querySelector('#root>*') || document.querySelector('header')).insertAdjacentElement('beforebegin', el); 2227 | } 2228 | 2229 | // 获取要排除的tag 2230 | function get_NotNeed_Tag () { 2231 | let temp_not_need_tag = XZForm.setTagNotNeed.value; 2232 | if (temp_not_need_tag === '') { //如果没有设置 tag,则重置 2233 | notNeed_tag = []; 2234 | } else { 2235 | notNeed_tag = temp_not_need_tag.split(','); 2236 | if (notNeed_tag[notNeed_tag.length - 1] === '') { //处理最后一位是逗号的情况 2237 | notNeed_tag.pop(); 2238 | } 2239 | addOutputInfo('
    ' + xzlt('_设置了排除tag之后的提示') + notNeed_tag.join(',')); 2240 | } 2241 | } 2242 | 2243 | // 获取必须包含的tag 2244 | function get_Need_Tag () { 2245 | let temp_need_tag = XZForm.setTagNeed.value; 2246 | if (temp_need_tag === '') { //如果没有设置 tag,则重置 2247 | need_tag = []; 2248 | } else { 2249 | need_tag = temp_need_tag.split(','); 2250 | if (need_tag[need_tag.length - 1] === '') { //处理最后一位是逗号的情况 2251 | need_tag.pop(); 2252 | } 2253 | addOutputInfo('
    ' + xzlt('_设置了必须tag之后的提示') + need_tag.join(',')); 2254 | } 2255 | } 2256 | 2257 | // 检查过滤宽高的设置 2258 | function checkSetWH () { 2259 | let check_result_width = checkNumberGreater0(XZForm.setWidth.value); 2260 | let check_result_height = checkNumberGreater0(XZForm.setHeight.value); 2261 | if (check_result_width || check_result_height) { // 宽高只要有一个条件大于 0 即可 2262 | is_set_filterWH = true; 2263 | filterWH = { 2264 | and_or: XZForm.setWidth_AndOr.value, 2265 | width: check_result_width ? check_result_width.value : 0, 2266 | height: check_result_height ? check_result_height.value : 0 2267 | }; 2268 | } else { 2269 | is_set_filterWH = false; 2270 | } 2271 | if (is_set_filterWH) { 2272 | let and_or = filterWH.and_or; 2273 | addOutputInfo('
    ' + xzlt('_设置了筛选宽高之后的提示文字p1') + filterWH.width + and_or.replace('|', xzlt('_或者')).replace('&', xzlt('_并且')) + xzlt('_高度设置') + filterWH.height); 2274 | } 2275 | } 2276 | 2277 | // 检查过滤宽高是否通过 2278 | function checkSetWHOK (width, height) { 2279 | if (is_set_filterWH) { 2280 | if (width < filterWH.width && height < filterWH.height) { //如果宽高都小于要求的宽高 2281 | return false; 2282 | } else { 2283 | if (filterWH.and_or === '|') { 2284 | if (width >= filterWH.width || height >= filterWH.height) { //判断or的情况 2285 | return true; 2286 | } else { 2287 | return false; 2288 | } 2289 | } else if (filterWH.and_or === '&') { 2290 | if (width >= filterWH.width && height >= filterWH.height) { //判断and的情况 2291 | return true; 2292 | } else { 2293 | return false; 2294 | } 2295 | } 2296 | } 2297 | } else { 2298 | return true; 2299 | } 2300 | } 2301 | 2302 | // 检查过滤收藏数的设置 2303 | function checkSetBMK () { 2304 | let check_result = checkNumberGreater0(XZForm.setFavNum.value, '=0'); 2305 | if (check_result) { 2306 | filterBMK = check_result.value; 2307 | is_set_filterBMK = true; 2308 | } else { 2309 | is_set_filterBMK = false; 2310 | addOutputInfo('
    ' + xzlt('_参数不合法1')); 2311 | return false; 2312 | } 2313 | if (is_set_filterBMK && filterBMK > 0 && page_type !== 5) { 2314 | addOutputInfo('
    ' + xzlt('_设置了筛选收藏数之后的提示文字') + filterBMK); 2315 | } 2316 | return true; 2317 | } 2318 | 2319 | // 检查是否设置了只下载书签作品 2320 | function checkOnlyBMK () { 2321 | only_down_bmk = XZForm.setOnlyBMK.checked; 2322 | if (only_down_bmk) { 2323 | addOutputInfo('
    ' + xzlt('_只下载已收藏的提示')); 2324 | } 2325 | } 2326 | 2327 | // 检查输入的参数是否有效,要求大于 0 的数字 2328 | function checkNumberGreater0 (arg, mode) { 2329 | if (arg === null || arg === '') { 2330 | return false; 2331 | } 2332 | arg = parseInt(arg); 2333 | let min_num = 0; 2334 | if (mode === '=0') { // 允许最小为0 2335 | min_num = -1; 2336 | } 2337 | if (isNaN(arg) || arg <= min_num) { 2338 | // alert(xzlt('_本次输入的数值无效')); 2339 | return false; 2340 | } else { 2341 | return { 2342 | 'value': arg 2343 | }; 2344 | } 2345 | } 2346 | 2347 | // 最多有多少页,在 page_type 10 使用 2348 | function set_max_num () { 2349 | if (loc_url.includes('bookmark_new_illust')) { // 其实这个条件和条件2在一定程度上是重合的,所以这个必须放在前面。 2350 | max_num = 100; //关注的人的新作品(包含普通版和r18版)的最大页数都是100 2351 | } else if (loc_url.includes('new_illust.php')) { 2352 | max_num = 1000; //大家的新作品(普通版)的最大页数是1000 2353 | } else if (loc_url.includes('new_illust_r18.php')) { 2354 | max_num = 500; //大家的的新作品(r18版)的最大页数是500 2355 | } 2356 | } 2357 | 2358 | // 使用无刷新加载的页面需要监听 url 的改变 2359 | let _wr = function (type) { 2360 | let orig = history[type]; 2361 | return function () { 2362 | let rv = orig.apply(this, arguments); 2363 | let e = new Event(type); 2364 | e.arguments = arguments; 2365 | window.dispatchEvent(e); 2366 | return rv; 2367 | }; 2368 | }; 2369 | history.pushState = _wr('pushState'); 2370 | history.replaceState = _wr('replaceState'); 2371 | 2372 | // 设置要下载的个数 2373 | function set_requset_num () { // 下载相似作品、相关作品时 2374 | max_num = 500; //设置最大允许获取多少个作品。相似作品、相关作品的数字是可以改的,比如500,1000,这里限制为500。 2375 | let result = checkNumberGreater0(XZForm.setWantPage.value); 2376 | if (result) { 2377 | requset_number = result.value; 2378 | if (requset_number > max_num) { //如果超出最大值就按最大值处理 2379 | requset_number = max_num; 2380 | } 2381 | } else { 2382 | alert(xzlt('_参数不合法1')); 2383 | return false; 2384 | } 2385 | } 2386 | 2387 | // 获取作品页信息出错,如404 2388 | function illust_error (url) { 2389 | if (page_type === 1 && !down_xiangguan) { // 在作品页内下载时,设置的want_page其实是作品数 2390 | if (want_page > 0) { 2391 | want_page--; 2392 | } 2393 | // 在作品页内下载时,如果出现了无法访问的作品时,就获取不到接下来的作品了,直接结束。 2394 | addOutputInfo('
    ' + xzlt('_无权访问1', url) + '
    '); 2395 | allow_work = true; 2396 | allWorkFinished(); 2397 | } else { // 跳过当前作品 2398 | addOutputInfo('
    ' + xzlt('_无权访问2', url) + '
    '); 2399 | if (illust_url_list.length > 0) { //如果存在下一个作品,则 2400 | getIllustPage(illust_url_list[0]); 2401 | } else { //没有剩余作品 2402 | ajax_threads_finished++; 2403 | if (ajax_threads_finished === ajax_for_illust_threads) { //如果所有并发请求都执行完毕 2404 | ajax_threads_finished = 0; //复位 2405 | allow_work = true; 2406 | allWorkFinished(); 2407 | } 2408 | } 2409 | } 2410 | } 2411 | 2412 | // 检查用户页数设置 2413 | function check_want_page_rule1 (input_tip, error_tip, start1_tip, start2_tip) { 2414 | let temp_want_page = parseInt(XZForm.setWantPage.value); 2415 | if (parseInt(temp_want_page) < 1 && temp_want_page !== -1) { //比1小的数里,只允许-1, 0也不行 2416 | addOutputInfo(error_tip); 2417 | return false; 2418 | } 2419 | if (parseInt(temp_want_page) >= 1) { 2420 | want_page = temp_want_page; 2421 | addOutputInfo(start1_tip.replace('-num-', want_page)); 2422 | return true; 2423 | } else if (temp_want_page === -1) { 2424 | want_page = temp_want_page; 2425 | addOutputInfo(start2_tip); 2426 | return true; 2427 | } 2428 | } 2429 | 2430 | // 获取宽高比的设置 2431 | function getRatioSetting () { 2432 | ratio_type = XZForm.ratio.value; 2433 | if (ratio_type === '0') { 2434 | return false; 2435 | } 2436 | if (ratio_type === '3') { // 由用户输入 2437 | ratio_type = parseFloat(XZForm.user_ratio.value); 2438 | if (isNaN(ratio_type)) { 2439 | alert(xzlt('_宽高比必须是数字')); 2440 | ratio_type = '0'; 2441 | XZForm.ratio.value = ratio_type; 2442 | return false; 2443 | } 2444 | } 2445 | if (ratio_type === '1') { 2446 | addOutputInfo('
    ' + xzlt('_设置了宽高比之后的提示', xzlt('_横图'))); 2447 | } else if (ratio_type === '2') { 2448 | addOutputInfo('
    ' + xzlt('_设置了宽高比之后的提示', xzlt('_竖图'))); 2449 | } else { 2450 | addOutputInfo('
    ' + xzlt('_设置了宽高比之后的提示', xzlt('_输入宽高比') + ratio_type)); 2451 | } 2452 | return true; 2453 | } 2454 | 2455 | // 判断宽高比条件是否通过 2456 | function checkRatio (width, height) { 2457 | if (ratio_type === '0') { 2458 | return true; 2459 | } else if (ratio_type === '1') { 2460 | return (width / height > 1); 2461 | } else if (ratio_type === '2') { 2462 | return (width / height < 1); 2463 | } else { 2464 | return (width / height >= ratio_type); 2465 | } 2466 | } 2467 | 2468 | // 根据对象的属性排序 2469 | function sortByProperty (propertyName) { 2470 | return function (object1, object2) { 2471 | let value1 = parseInt(object1[propertyName]); 2472 | let value2 = parseInt(object2[propertyName]); 2473 | if (value2 < value1) { //倒序排列 2474 | return -1; 2475 | } else if (value2 > value1) { 2476 | return 1; 2477 | } else { 2478 | return 0; 2479 | } 2480 | }; 2481 | } 2482 | 2483 | // 对结果列表进行排序 2484 | function listSort () { 2485 | imgList.sort(sortByProperty('num')); 2486 | let list_wrap = document.querySelector(tag_search_list_wrap); 2487 | list_wrap.innerHTML = ''; 2488 | imgList.forEach(data => { 2489 | list_wrap.insertAdjacentHTML('beforeend', data.e); 2490 | }); 2491 | } 2492 | 2493 | // tag搜索页的筛选任务执行完毕 2494 | function tagSearchPageFinished () { 2495 | allow_work = true; 2496 | // listPage_finished=0; //不注释掉的话,每次添加筛选任务都是从当前页开始,而不是一直往后累计 2497 | listPage_finished2 = 0; //重置已抓取的页面数量 2498 | listSort(); 2499 | changeTitle('→'); 2500 | } 2501 | 2502 | // 获取 tag 搜索列表里的可见作品 2503 | function visibleList () { 2504 | let list = document.querySelectorAll(tag_search_list_selector); 2505 | return Array.from(list).filter(el => { 2506 | return el.style.display !== 'none'; 2507 | }); 2508 | } 2509 | 2510 | // 获取当前的页码,适用于有页码的页面 2511 | function getNowPageNo () { 2512 | if (document.querySelector('.page-list .current')) { //如果显示有页码 2513 | startpage_no = parseInt(document.querySelector('.page-list .current').textContent); //以当前页的页码为起始页码 2514 | } else { //否则认为只有1页 2515 | startpage_no = 1; 2516 | } 2517 | listPage_finished = 0; 2518 | } 2519 | 2520 | // 实现 remove() 方法 2521 | [HTMLCollection, NodeList].forEach(arg => { 2522 | arg.prototype.remove = function () { 2523 | if (Reflect.has(this, 'length')) { // 如果有 length 属性则循环删除。HTMLCollection 需要转化为数组才能使用 forEach,NodeList 不需要转化就可以使用 2524 | Array.from(this).forEach(el => el.parentNode.removeChild(el)); 2525 | } else { //没有 length 属性的,不能使用 forEach,直接删除(querySelector、getElementById 没有 length 属性) 2526 | this.parentNode.removeChild(this); 2527 | } 2528 | }; 2529 | }); 2530 | 2531 | // 实现 toggle 方法,仅支持 block 和 none 切换 2532 | function toggle (el) { 2533 | el.style.display = (el.style.display === 'block') ? 'none' : 'block'; 2534 | } 2535 | 2536 | // 显示调整后的列表数量,仅在某些页面中使用 2537 | function outputNowResult () { 2538 | insertOutputInfo(); 2539 | addOutputInfo(xzlt('_调整完毕', visibleList().length) + '
    '); 2540 | } 2541 | 2542 | // 添加图片信息 2543 | function addImgInfo (id, imgUrl, title, nowAllTag, user, userid, fullWidth, fullHeight, ext, bmk) { 2544 | img_info.push({ 2545 | id: id, 2546 | url: imgUrl, 2547 | title: title, 2548 | tags: nowAllTag, 2549 | user: user, 2550 | userid: userid, 2551 | fullWidth: fullWidth, 2552 | fullHeight: fullHeight, 2553 | ext: ext, 2554 | bmk: bmk 2555 | }); 2556 | } 2557 | 2558 | // 启动抓取 2559 | function startGet () { 2560 | if (!allow_work || download_started) { 2561 | alert(xzlt('_当前任务尚未完成1')); 2562 | return false; 2563 | } 2564 | 2565 | insertOutputInfo(); 2566 | document.querySelector('.download_panel').style.display = 'none'; 2567 | // 设置要获取的作品数或页数 2568 | if (page_type === 1) { 2569 | if (quick) { // 快速下载 2570 | want_page = 1; 2571 | } else if (!down_xiangguan) { // 手动设置下载页数 2572 | let result = check_want_page_rule1( 2573 | xzlt('_check_want_page_rule1_arg1'), 2574 | xzlt('_check_want_page_rule1_arg2'), 2575 | xzlt('_check_want_page_rule1_arg3'), 2576 | xzlt('_check_want_page_rule1_arg4') 2577 | ); 2578 | if (!result) { 2579 | return false; 2580 | } 2581 | } 2582 | } else if (page_type === 2) { 2583 | let result = check_want_page_rule1( 2584 | xzlt('_check_want_page_rule1_arg5'), 2585 | xzlt('_check_want_page_rule1_arg2'), 2586 | xzlt('_check_want_page_rule1_arg6'), 2587 | xzlt('_check_want_page_rule1_arg7') 2588 | ); 2589 | if (!result) { 2590 | return false; 2591 | } 2592 | } else if (page_type === 5) { 2593 | document.querySelectorAll('._premium-lead-popular-d-body').remove(); // 去除热门作品一栏 2594 | let result = check_want_page_rule1( 2595 | xzlt('_check_want_page_rule1_arg5'), 2596 | xzlt('_check_want_page_rule1_arg2'), 2597 | '', 2598 | xzlt('_check_want_page_rule1_arg7') 2599 | ); 2600 | if (!result) { 2601 | return false; 2602 | } 2603 | if (want_page === -1) { 2604 | want_page = 1000; 2605 | } 2606 | // 这里直接获取收藏数,可能是非法的,下面再检查 2607 | addOutputInfo(xzlt('_tag搜索任务开始', parseInt(XZForm.setFavNum.value), want_page)); 2608 | if (!listPage_finished) { //如果是首次抓取 则处理当前页面 2609 | document.querySelectorAll(tag_search_list_selector).remove(); // 移除当前列表内容 2610 | } 2611 | } else if (page_type === 10) { 2612 | let result = checkNumberGreater0(XZForm.setWantPage.value); 2613 | if (!result) { 2614 | alert(xzlt('_参数不合法1')); 2615 | return false; 2616 | } else if (result.value > max_num) { 2617 | alert(xzlt('_输入超过了最大值') + max_num); 2618 | return false; 2619 | } else { 2620 | want_page = result.value; 2621 | addOutputInfo(xzlt('_任务开始1', want_page)); 2622 | } 2623 | } 2624 | if (page_type === 7) { 2625 | listPage_finished = 0; 2626 | } 2627 | // 检查是否设置了收藏数要求 2628 | if (!checkSetBMK()) { 2629 | return false; 2630 | } 2631 | 2632 | if (page_type !== 5) { // tag搜索页里,这些设置此时无法生效,所以放在后面开始下载时再检查 2633 | // 检查是否设置了多图作品的张数限制 2634 | check_multiple_down_number(); 2635 | // 获取必须包含的tag 2636 | get_Need_Tag(); 2637 | // 获取要排除的tag 2638 | get_NotNeed_Tag(); 2639 | } 2640 | 2641 | // 检查是否设置了只下载书签作品 2642 | checkOnlyBMK(); 2643 | // 检查排除作品类型的设置 2644 | if (checkNotDownType() === false) { 2645 | return false; 2646 | } 2647 | // 检查是否设置了宽高条件 2648 | checkSetWH(); 2649 | // 检查宽高比设置 2650 | getRatioSetting(); 2651 | resetResult(); 2652 | 2653 | if (page_type !== 6) { 2654 | allow_work = false; //开始执行时更改许可状态 2655 | } 2656 | 2657 | now_tips = outputInfo.innerHTML; 2658 | 2659 | if (page_type === 0) { 2660 | outputInfo.innerHTML = now_tips + xzlt('_开始获取作品页面'); 2661 | getListUrlFinished(); //通过id抓取时,不需要获取列表页 2662 | } else if (page_type === 1) { 2663 | if (down_xiangguan) { // 下载相关作品 2664 | getListPage(); 2665 | } else { 2666 | getIllustPage(window.location.href); //开始获取图片。因为新版作品页切换作品不需要刷新页面了,所以要传递实时的url。 2667 | } 2668 | } else if (page_type === 2) { 2669 | readyGetListPage3(); 2670 | } else if (page_type === 6) { 2671 | getListPage2(); 2672 | } else { 2673 | getListPage(); //开始获取列表页 2674 | } 2675 | } 2676 | 2677 | // 获取作品列表页 2678 | function getListPage () { 2679 | changeTitle('↑'); 2680 | let url; 2681 | if (page_type === 9 || down_xiangguan) { 2682 | let id; //取出作品id 2683 | if (location.href.includes('recommended.php')) { // '为你推荐'里面的示例作品id为'auto' 2684 | id = 'auto'; 2685 | } else { 2686 | id = getIllustId(); // 作品页的url需要实时获取 2687 | } 2688 | url = '/rpc/recommender.php?type=illust&sample_illusts=' + id + '&num_recommendations=' + requset_number; //获取相似的作品 2689 | } else if (page_type === 11) { // 对于发现图片,仅下载已有部分,所以不需要去获取列表页了。 2690 | let now_illust = document.querySelectorAll('.QBU8zAz>a'); //获取已有作品 ._3NnoQkv>a 2691 | Array.from(now_illust).forEach(el => { //拼接作品的url 2692 | // discovery列表的url也是有额外后缀的,需要去掉 2693 | illust_url_list.push(el.href.split('&uarea')[0]); 2694 | }); 2695 | addOutputInfo('
    ' + xzlt('_列表页获取完成2', illust_url_list.length)); 2696 | getListUrlFinished(); 2697 | return false; 2698 | } else { 2699 | url = base_url + (startpage_no + listPage_finished); 2700 | } 2701 | 2702 | fetch(url) 2703 | .then(response => { 2704 | if (response.ok) { 2705 | return response.text(); 2706 | } else { 2707 | return Promise.reject({ 2708 | status: response.status, 2709 | statusText: response.statusText 2710 | }); 2711 | } 2712 | }) 2713 | .then(data => { 2714 | listPage_finished++; 2715 | let listPage_document; 2716 | if (page_type !== 7 && page_type !== 9 && !down_xiangguan) { // 排行榜和相似作品、相关作品,直接获取json数据,不需要解析为DOM 2717 | listPage_document = (new DOMParser()).parseFromString(data, 'text/html'); 2718 | } 2719 | if (page_type === 5) { // tag搜索页 2720 | listPage_finished2++; 2721 | let this_one_info; 2722 | this_one_info = listPage_document.querySelector(tag_search_lv1_selector).getAttribute('data-items'); // 保存这一次的信息 2723 | this_one_info = JSON.parse(this_one_info); // 转化为数组 2724 | // 删除广告信息 2725 | this_one_info.forEach((val, index, array) => { 2726 | if (val.isAdContainer) { 2727 | array.splice(index, 1); 2728 | } 2729 | }); 2730 | display_cover = XZForm.setDisplayCover.checked; 2731 | let list_wrap = document.querySelector(tag_search_list_wrap); 2732 | for (const data of this_one_info) { 2733 | // 在这里进行一些检查 2734 | // 检查收藏设置 2735 | let shoucang = data['bookmarkCount']; 2736 | if (shoucang < filterBMK) { 2737 | continue; 2738 | } 2739 | // 检查宽高设置和宽高比设置 2740 | let ture_width = parseInt(data['width']); 2741 | let ture_height = parseInt(data['height']); 2742 | if (!checkSetWHOK(ture_width, ture_height) || !checkRatio(ture_width, ture_height)) { 2743 | continue; 2744 | } 2745 | // 检查只下载书签作品的设置 2746 | let isBookmarked = data['isBookmarked']; 2747 | if (only_down_bmk) { 2748 | if (!isBookmarked) { 2749 | continue; 2750 | } 2751 | } 2752 | // 检查排除类型设置 2753 | let pageCount = parseInt(data['pageCount']); // 包含的图片数量 2754 | let illustType = data['illustType']; // 作品类型 0 插画 1 漫画 2 动图 2755 | let now_type = '1'; // 我定义的类型 1 单图 2 多图 3 动图 2756 | if (pageCount > 1) { // 多图 2757 | now_type = '2'; 2758 | } 2759 | if (illustType === '2') { // 动图 2760 | now_type = '3'; 2761 | } 2762 | if (notdown_type.includes(now_type)) { 2763 | continue; 2764 | } 2765 | // 检查通过后,拼接每个作品的html 2766 | let new_html = tag_search_new_html; 2767 | if (isBookmarked) { 2768 | new_html = new_html.replace(/xz_isBookmarked/g, 'on'); 2769 | } 2770 | if (pageCount > 1) { 2771 | new_html = new_html.replace('', xz_multiple_html); 2772 | } 2773 | if (illustType === '2') { 2774 | new_html = new_html.replace('', xz_gif_html); 2775 | } 2776 | new_html = new_html.replace(/xz_illustId/g, data['illustId']).replace(/xz_pageCount/g, data['pageCount']); 2777 | if (display_cover) { 2778 | new_html = new_html.replace(/xz_url/g, data['url']); 2779 | } else { 2780 | new_html = new_html.replace(/xz_url/g, ''); 2781 | } 2782 | new_html = new_html.replace(/xz_illustTitle/g, data['illustTitle']) 2783 | .replace(/xz_userId/g, data['userId']) 2784 | .replace(/xz_userName/g, data['userName']) 2785 | .replace(/xz_userImage/g, data['userImage']) 2786 | .replace(/xz_bookmarkCount/g, data['bookmarkCount']); 2787 | // 设置宽高 2788 | let max_width = '198'; 2789 | let max_height = '198'; 2790 | if (ture_width >= ture_height) { 2791 | new_html = new_html.replace(/xz_width/g, max_width).replace(/xz_height/g, 'auto'); 2792 | } else { 2793 | new_html = new_html.replace(/xz_width/g, 'auto').replace(/xz_height/g, max_height); 2794 | } 2795 | imgList.push({ 2796 | 'id': data['illustId'], 2797 | 'e': new_html, 2798 | 'num': Number(shoucang) 2799 | }); 2800 | list_wrap.insertAdjacentHTML('beforeend', new_html); 2801 | } 2802 | outputInfo.innerHTML = now_tips + '
    ' + xzlt('_tag搜索页已抓取多少页', listPage_finished2, want_page, startpage_no + listPage_finished - 1); 2803 | //判断任务状态 2804 | if (listPage_finished2 == want_page) { 2805 | allow_work = true; 2806 | addOutputInfo('
    ' + xzlt('_tag搜索页任务完成1', document.querySelectorAll(tag_search_list_selector).length) + '

    '); 2807 | tagSearchPageFinished(); 2808 | return false; 2809 | } else if (!listPage_document.querySelector('.next ._button')) { //到最后一页了,已抓取本tag的所有页面 2810 | allow_work = true; 2811 | addOutputInfo('
    ' + xzlt('_tag搜索页任务完成2', document.querySelectorAll(tag_search_list_selector).length) + '

    '); 2812 | tagSearchPageFinished(); 2813 | return false; 2814 | } else if (interrupt) { //任务被用户中断 2815 | addOutputInfo('
    ' + xzlt('_tag搜索页中断', document.querySelectorAll(tag_search_list_selector).length) + '

    '); 2816 | interrupt = false; 2817 | tagSearchPageFinished(); 2818 | return false; 2819 | } else { 2820 | getListPage(); 2821 | } 2822 | } else if (page_type === 7) { // 其他排行榜。地区排行榜不经过这个步骤 2823 | let contents = JSON.parse(data).contents; //取出作品信息列表 2824 | contents.forEach(data => { 2825 | let nowClass = ''; 2826 | let pageCount = parseInt(data.illust_page_count); // 包含的图片数量 2827 | if (pageCount > 1) { // 多图 2828 | nowClass = 'multiple'; 2829 | } 2830 | if (data.illust_type === '2') { // 作品类型 0 插画 1 漫画 2 动图 2831 | nowClass = 'ugoku-illust'; 2832 | } 2833 | let nowHref = 'https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + data.illust_id; 2834 | let bookmarked = data.is_bookmarked; 2835 | checkNotDownType_result(nowClass, nowHref, bookmarked); 2836 | }); 2837 | outputInfo.innerHTML = now_tips + '
    ' + xzlt('_排行榜进度', listPage_finished); 2838 | if (listPage_finished == part_number) { 2839 | addOutputInfo('
    ' + xzlt('_排行榜任务完成', illust_url_list.length)); 2840 | getListUrlFinished(); 2841 | } else { 2842 | getListPage(); 2843 | } 2844 | } else if (page_type === 9 || down_xiangguan) { //添加收藏后的相似作品 2845 | let illust_list = JSON.parse(data).recommendations; //取出id列表 2846 | illust_list.forEach(data => { //拼接作品的url 2847 | illust_url_list.push('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + data); 2848 | }); 2849 | addOutputInfo('
    ' + xzlt('_列表页获取完成2', illust_url_list.length)); 2850 | getListUrlFinished(); 2851 | } else { // 不要把下面的if和这个else合并 2852 | if (page_type === 10 && list_is_new === true) { //关注的新作品 列表改成和tag搜索页一样的了 2853 | let this_one_info = listPage_document.querySelector(tag_search_lv1_selector).getAttribute('data-items'); // 保存这一次的信息 2854 | this_one_info = JSON.parse(this_one_info); // 转化为数组 2855 | this_one_info.forEach(data => { 2856 | let nowClass = ''; 2857 | let bookmarked; 2858 | let nowHref = 'https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + data['illustId']; 2859 | let pageCount = parseInt(data['pageCount']); // 包含的图片数量 2860 | if (pageCount > 1) { // 多图 2861 | nowClass = 'multiple'; 2862 | } 2863 | let illustType = data['illustType']; // 作品类型 0 插画 1 漫画 2 动图 2864 | if (illustType === '2') { // 动图 2865 | nowClass = 'ugoku-illust'; 2866 | } 2867 | if (data['isBookmarked']) { // 是否已收藏 2868 | bookmarked = true; 2869 | } 2870 | checkNotDownType_result(nowClass, nowHref, bookmarked); 2871 | }); 2872 | } else { 2873 | let allPicArea = listPage_document.querySelectorAll('._image-items .image-item'); 2874 | for (const el of allPicArea) { 2875 | if (el.querySelector('.title').getAttribute('title') === '-----') { //如果这个作品被删除、或非公开 2876 | continue; 2877 | } 2878 | let nowClass = el.querySelector('a').getAttribute('class'); 2879 | let nowHref = el.querySelector('a').getAttribute('href'); 2880 | let bookmarked = el.querySelector('._one-click-bookmark').classList.contains('on'); 2881 | checkNotDownType_result(nowClass, nowHref, bookmarked); 2882 | } 2883 | } 2884 | 2885 | outputInfo.innerHTML = now_tips + '
    ' + xzlt('_列表页抓取进度', listPage_finished); 2886 | //判断任务状态 2887 | if (!listPage_document.querySelector('.next ._button') || listPage_finished == want_page) { //如果没有下一页的按钮或者抓取完指定页面 2888 | allow_work = true; 2889 | listPage_finished = 0; 2890 | addOutputInfo('
    ' + xzlt('_列表页抓取完成')); 2891 | if (illust_url_list.length === 0) { //没有符合条件的作品 2892 | addOutputInfo('
    ' + xzlt('_列表页抓取结果为零')); 2893 | return false; 2894 | } 2895 | getListUrlFinished(); 2896 | } else { 2897 | getListPage(); 2898 | } 2899 | } 2900 | }) 2901 | .catch(error => { 2902 | console.log(error); 2903 | if (error.status === 404) { 2904 | if (page_type === 7) { //其他排行榜 2905 | //如果发生了404错误,则中断抓取,直接下载已有部分。(因为可能确实没有下一部分了,只是这种情况我们没见到。这样的话之前预设的最大页数可能就不对 2906 | console.log('404错误,直接下载已有部分'); 2907 | addOutputInfo('
    ' + xzlt('_排行榜列表页抓取遇到404', illust_url_list.length) + '

    '); 2908 | getListUrlFinished(); 2909 | } 2910 | } 2911 | }); 2912 | } 2913 | 2914 | // 第二个获取列表的函数,仅在tag搜索页和地区排行榜使用(不使用 ajax,从当前列表页直接获取所有内容页的列表) 2915 | function getListPage2 () { 2916 | changeTitle('↑'); 2917 | if (!allow_work) { 2918 | alert(xzlt('_当前任务尚未完成2')); 2919 | return false; 2920 | } 2921 | if (page_type === 5) { 2922 | if (visibleList().length === 0) { 2923 | return false; 2924 | } 2925 | if (interrupt) { 2926 | interrupt = false; 2927 | } 2928 | illust_url_list = []; 2929 | resetResult(); 2930 | // 因为tag搜索页里的下载按钮没有启动 startGet,而是在这里,所以有些检查在这里进行 2931 | // 这里有一些检查是第二次执行,应对用户筛选完成后,改动设置的情况 2932 | // 检查排除作品类型的设置 2933 | if (checkNotDownType() === false) { 2934 | return false; 2935 | } 2936 | // 检查是否设置了宽高条件 2937 | checkSetWH(); 2938 | // 检查宽高比设置 2939 | getRatioSetting(); 2940 | // 检查是否设置了只下载书签作品 2941 | checkOnlyBMK(); 2942 | // 检查是否设置了多图作品的张数限制 2943 | check_multiple_down_number(); 2944 | // 获取必须包含的tag 2945 | get_Need_Tag(); 2946 | // 获取要排除的tag 2947 | get_NotNeed_Tag(); 2948 | } 2949 | allow_work = false; 2950 | if (page_type === 5) { // tag搜索页 2951 | let allPicArea = visibleList(); 2952 | for (const el of allPicArea) { 2953 | // 因为此页面类型里,判断作品类型的class与其他页面不同,所以在这里转换成能被接下来的函数识别的字符 2954 | let nowClass = ''; 2955 | if (el.querySelector(tag_search_multiple_selector)) { 2956 | nowClass = 'multiple'; 2957 | } else if (el.querySelector(tag_search_gif_selector)) { 2958 | nowClass = 'ugoku-illust'; 2959 | } 2960 | let nowHref = el.querySelector('a').href; 2961 | let bookmarked = el.querySelector('._one-click-bookmark').classList.contains('on'); 2962 | checkNotDownType_result(nowClass, nowHref, bookmarked); 2963 | } 2964 | } else { // 地区排行榜 2965 | let allPicArea = document.querySelectorAll('.ranking-item>.work_wrapper>a'); 2966 | allPicArea.forEach(el => { 2967 | let nowClass = el.getAttribute('class'); 2968 | let nowHref = el.href; 2969 | let bookmarked = el.querySelector('._one-click-bookmark').classList.contains('on'); 2970 | checkNotDownType_result(nowClass, nowHref, bookmarked); 2971 | }); 2972 | } 2973 | insertOutputInfo(); 2974 | addOutputInfo('
    ' + xzlt('_列表抓取完成开始获取作品页', illust_url_list.length)); 2975 | if (illust_url_list.length <= 0) { 2976 | addOutputInfo('
    ' + xzlt('_参数不合法1')); 2977 | } 2978 | getListUrlFinished(); 2979 | } 2980 | 2981 | // 获取作品id,可以传参,无参数则从当前 url 匹配 2982 | function getIllustId(url) { 2983 | const str = url || window.location.search || loc_url; 2984 | if (str.includes('illust_id')) { 2985 | // 传统 url 2986 | return /illust_id=(\d*\d)/.exec(str)[1]; 2987 | } 2988 | else if (str.includes('/artworks/')) { 2989 | // 新版 url 2990 | return /artworks\/(\d*\d)/.exec(str)[1]; 2991 | } 2992 | else { 2993 | // 直接取出 url 中的数字 2994 | return /\d*\d/.exec(loc_url)[0]; 2995 | } 2996 | } 2997 | 2998 | // 获取用户id 2999 | function getUserId() { 3000 | let userId = ''; 3001 | // 首先尝试从 url 中获取 3002 | const test = /(\?|&)id=(\d{1,9})/.exec(window.location.search); 3003 | const nameElement = document.querySelector('.user-name'); 3004 | if (test) { 3005 | userId = test[2]; 3006 | } 3007 | else if (nameElement) { 3008 | // 从旧版页面的头像获取(在书签页面使用) 3009 | userId = /\?id=(\d{1,9})/.exec(nameElement.href)[1]; 3010 | } 3011 | else { 3012 | // 从新版页面的头像获取,因为经常改版,不得已改成从源码匹配了 3013 | const el = document.getElementById('root') || document.getElementById('spa-contents'); 3014 | // 在 PC 模式的新版页面使用 root,在手机模式的新版页面使用 spa-contents 3015 | userId = /member\.php\?id=(\d{1,9})/.exec(el.innerHTML)[1]; 3016 | } 3017 | return userId; 3018 | } 3019 | 3020 | // 获取作品信息,包含对动图的处理 3021 | async function getIllustInfo () { 3022 | if (download_gif_btn) { 3023 | download_gif_btn.style.display = 'none'; // 隐藏动图转换按钮 3024 | } 3025 | 3026 | let response = await fetch('https://www.pixiv.net/ajax/illust/' + getIllustId(), { 3027 | method: 'get', 3028 | credentials: 'include', // 附带 cookie 3029 | }); 3030 | let data = await response.json(); 3031 | p_user = data.body.userName; 3032 | // 处理动图 3033 | if (data.body.illustType === 2) { 3034 | initGIF(); 3035 | } 3036 | return data.body; 3037 | } 3038 | 3039 | // 获取用户名称 3040 | // 测试用户 https://www.pixiv.net/member.php?id=2793583 他的用户名比较特殊 3041 | function getUserName () { 3042 | let result = ''; 3043 | if (page_type === 1) { // 内容页 3044 | result = p_user; 3045 | } else { // 画师作品列表页 3046 | let titleContent = document.querySelector('meta[property="og:title"]').content; // リング@「 シスコン 」 [pixiv] 3047 | result = titleContent.substr(0, titleContent.length - 7).replace(/ {1,9}$/, ''); // 有时候末尾会有空格,要去掉 3048 | } 3049 | return result; 3050 | } 3051 | 3052 | // 从 url 中取出指定的查询条件 3053 | function getQuery (input, query) { 3054 | let arr1 = input.split('?'); 3055 | let queryPart = []; 3056 | let result = {}; 3057 | if (arr1.length > 1) { 3058 | queryPart = arr1[1]; 3059 | } else { 3060 | return false; 3061 | } 3062 | queryPart = queryPart.split('&'); 3063 | queryPart.forEach(el => { 3064 | let arr2 = el.split('='); 3065 | if (arr2.length > 0) { 3066 | result[arr2[0]] = arr2[1]; 3067 | } 3068 | }); 3069 | return result[query]; 3070 | } 3071 | 3072 | // 在 page_type 2 使用,准备获取作品 id 列表 3073 | function readyGetListPage3 () { 3074 | // 每次开始时重置一些条件 3075 | offset_number = 0; 3076 | type2_id_list = []; 3077 | works_type = 0; 3078 | // works_type: 3079 | // 0 插画和漫画全都要,但是不带 tag 3080 | // 4 插画和漫画全都要,带 tag 3081 | // 1 只要插画 3082 | // 2 只要漫画 3083 | // 3 书签作品 3084 | tag_mode = getQuery(loc_url, 'tag') ? true : false; // 是否是 tag 模式 3085 | 3086 | // 每页个数 3087 | let once_number = 48; // 新版每页 48 个作品(因为新版不显示无法访问的作品,所以有时候一页不足这个数量) 3088 | if (document.querySelector('.user-name')) { // 旧版每页 20 个作品 3089 | once_number = 20; 3090 | } 3091 | 3092 | // 如果前面有页数,就去掉前面页数的作品数量。即:从本页开始下载 3093 | let now_page = getQuery(loc_url, 'p'); // 判断当前处于第几页 3094 | if (now_page) { 3095 | offset_number = (now_page - 1) * once_number; 3096 | } 3097 | if (offset_number < 0) { 3098 | offset_number = 0; 3099 | } 3100 | 3101 | // 根据页数设置,计算要下载的个数 3102 | requset_number = 0; 3103 | if (want_page === -1) { 3104 | requset_number = 9999999; 3105 | } else { 3106 | requset_number = once_number * want_page; 3107 | } 3108 | 3109 | // 根据不同的页面类型,选择不同的 API 来获取 id 列表 3110 | let api_url = `https://www.pixiv.net/ajax/user/${getUserId()}/profile/all`; 3111 | if (loc_url.includes('member.php?id=')) { // 资料页主页 3112 | // 采用默认设置即可,无需进行处理 3113 | } else if (/member_illust\.php\?.*id=/.test(loc_url)) { // 作品列表页 3114 | if (getQuery(loc_url, 'type') === 'illust') { // 插画分类 3115 | works_type = 1; 3116 | if (tag_mode) { // 带 tag 3117 | api_url = `https://www.pixiv.net/ajax/user/${getUserId()}/illusts/tag?tag=${getQuery(loc_url, 'tag')}&offset=${offset_number}&limit=${requset_number}`; 3118 | } 3119 | } else if (getQuery(loc_url, 'type') === 'manga') { // 漫画分类 3120 | works_type = 2; 3121 | if (tag_mode) { // 带 tag 3122 | api_url = `https://www.pixiv.net/ajax/user/${getUserId()}/manga/tag?tag=${getQuery(loc_url, 'tag')}&offset=${offset_number}&limit=${requset_number}`; 3123 | } 3124 | } else if (tag_mode) { // url 里没有插画也没有漫画,但是有 tag,则是在资料页首页点击了 tag,需要同时获取插画和漫画 3125 | works_type = 4; 3126 | api_url = `https://www.pixiv.net/ajax/user/${getUserId()}/illustmanga/tag?tag=${getQuery(loc_url, 'tag')}&offset=${offset_number}&limit=${requset_number}`; 3127 | } 3128 | } else if (loc_url.includes('bookmark.php')) { // 书签页面,需要多次循环获取 3129 | works_type = 3; 3130 | let rest_mode = 'show'; // 公开或非公开 3131 | if (getQuery(loc_url, 'rest') === 'hide') { 3132 | rest_mode = 'hide'; 3133 | } 3134 | let now_tag = ''; // 要使用的tag 3135 | if (getQuery(loc_url, 'untagged') == 1) { // “未分类”页面,设置 tag 3136 | now_tag = encodeURI('未分類'); 3137 | } 3138 | if (tag_mode) { // 如果有 tag 3139 | now_tag = getQuery(loc_url, 'tag'); 3140 | } 3141 | api_url = `https://www.pixiv.net/ajax/user/${getUserId()}/illusts/bookmarks?tag=${now_tag}&offset=${offset_number}&limit=${once_request}&rest=${rest_mode}`; 3142 | } else { // 不进行抓取 3143 | allow_work = true; 3144 | return false; 3145 | } 3146 | 3147 | changeTitle('↑'); 3148 | getListPage3(api_url); 3149 | addOutputInfo('
    ' + xzlt('_正在抓取')); 3150 | if (works_type === 3 && want_page === -1) { 3151 | addOutputInfo('
    ' + xzlt('_获取全部书签作品')); 3152 | } 3153 | } 3154 | 3155 | // 获取 page_type 2 的作品 id 列表 3156 | function getListPage3 (url) { 3157 | let bmk_get_end = false; // 书签作品是否获取完毕 3158 | fetch(url, { 3159 | credentials: "same-origin" 3160 | }) 3161 | .then(response => { 3162 | if (response.ok) { 3163 | return response.json(); 3164 | } else { 3165 | return Promise.reject({ 3166 | status: response.status, 3167 | statusText: response.statusText 3168 | }); 3169 | } 3170 | }) 3171 | .then(data => { 3172 | if (works_type !== 3) { // 获取非书签页面的作品(插画、漫画、或者全部) 3173 | if (!tag_mode) { // 不带 tag 3174 | // https://www.pixiv.net/ajax/user/27517/profile/all 3175 | if (works_type === 0) { // 获取全部插画和漫画 3176 | type2_id_list = type2_id_list.concat(Object.keys(data.body.illusts)).concat(Object.keys(data.body.manga)); 3177 | } else if (works_type === 1 || works_type === 5) { // 插画 或 动图 3178 | type2_id_list = type2_id_list.concat(Object.keys(data.body.illusts)); 3179 | } else if (works_type === 2) { // 漫画 3180 | type2_id_list = type2_id_list.concat(Object.keys(data.body.manga)); 3181 | } 3182 | } else { // 带 tag 的话 3183 | if (works_type === 1 || works_type === 2 || works_type === 4) { // 插画、漫画、或者全都要并带 tag ,数据结构都一样 3184 | // https://www.pixiv.net/ajax/user/27517/illusts/tag?tag=%E5%A5%B3%E3%81%AE%E5%AD%90&offset=0&limit=9999999 3185 | // https://www.pixiv.net/ajax/user/27517/manga/tag?tag=%E5%A5%B3%E3%81%AE%E5%AD%90&offset=0&limit=9999999 3186 | // https://www.pixiv.net/ajax/user/544479/illustmanga/tag?tag=%E6%9D%B1%E9%A2%A8%E8%B0%B7%E6%97%A9%E8%8B%97&offset=0&limit=9999999 3187 | let works = data.body.works; 3188 | works.forEach(data => type2_id_list.push(data.id)); 3189 | } else if (works_type === 5) { // 动图 3190 | type2_id_list = type2_id_list.concat(Object.keys(data.body.illusts)); 3191 | } 3192 | } 3193 | } else { // 书签页面,数据结构和 works_type 1、2 基本一样 3194 | // https://www.pixiv.net/ajax/user/9460149/illusts/bookmarks?tag=&offset=0&limit=100&rest=show 3195 | // https://www.pixiv.net/ajax/user/9460149/illusts/bookmarks?tag=推荐&offset=0&limit=100&rest=show 3196 | let works = data.body.works; 3197 | if (works.length === 0 || type2_id_list.length >= requset_number) { // 获取数量超出实际存在数量,works 长度为 0 3198 | bmk_get_end = true; 3199 | } else { 3200 | works.forEach(data => type2_id_list.push(data.id)); 3201 | } 3202 | } 3203 | 3204 | if (type2_id_list.length > 0) { 3205 | if (works_type === 0 || (works_type === 1 && !tag_mode) || (works_type === 2 && !tag_mode)) { // 非 tag 页,并且非 tag 页 3206 | // 在获取全部作品时(即使用默认的 api 时),由于 API 里不能设置 requset_number,所以要在这里处理。 3207 | // 把 id 从小到大排序 3208 | // 转换成数字 3209 | type2_id_list = type2_id_list.map(id => { 3210 | return parseInt(id); 3211 | }); 3212 | // 升序排列 3213 | type2_id_list.sort(function (x, y) { 3214 | return x - y; 3215 | }); 3216 | // 删除后面的 id(删除不需要的近期作品) 3217 | type2_id_list.splice(type2_id_list.length - offset_number, type2_id_list.length); 3218 | } 3219 | 3220 | // 获取完毕,不需要重复调用本函数的情况 3221 | if (works_type !== 3 || bmk_get_end) { 3222 | // 删除多余的作品 3223 | if (type2_id_list.length > requset_number) { 3224 | if (works_type !== 3) { // 删除前面部分 3225 | type2_id_list.splice(0, type2_id_list.length - requset_number); 3226 | } else { // 书签作品需要删除后面部分 3227 | type2_id_list.splice(requset_number, type2_id_list.length); 3228 | } 3229 | } 3230 | // 重置之前的结果 3231 | illust_url_list = []; 3232 | // 拼接作品的url 3233 | type2_id_list.forEach(id => { 3234 | illust_url_list.push('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + id); 3235 | }); 3236 | // 获取 id 列表完成 3237 | addOutputInfo('
    ' + xzlt('_列表抓取完成开始获取作品页', illust_url_list.length)); 3238 | getListUrlFinished(); 3239 | } else if (works_type === 3 && !bmk_get_end) { // 如果是书签页,且没有获取完毕,则重复执行 3240 | offset_number += once_request; // 每次增加偏移量,并获取之后固定数量 3241 | url = url.replace(/offset=\d*\d?/, `offset=${offset_number}`); 3242 | getListPage3(url); 3243 | } 3244 | } else { 3245 | addOutputInfo('
    ' + xzlt('_列表页抓取结果为零')); 3246 | allow_work = true; 3247 | return false; 3248 | } 3249 | }) 3250 | .catch(error => console.log(error)); 3251 | } 3252 | 3253 | // 作品列表获取完毕,开始抓取图片内容页 3254 | function getListUrlFinished () { 3255 | now_tips = outputInfo.innerHTML; 3256 | if (illust_url_list.length < ajax_for_illust_threads) { 3257 | ajax_for_illust_threads = illust_url_list.length; 3258 | } 3259 | for (let i = 0; i < ajax_for_illust_threads; i++) { 3260 | setTimeout(getIllustPage(illust_url_list[0]), i * ajax_for_illust_delay); 3261 | } 3262 | } 3263 | 3264 | // 获取作品内容页面的函数 3265 | function getIllustPage (url) { 3266 | /* 3267 | url参数为完整的作品url,或者不包含根路径的作品url,如: 3268 | https://www.pixiv.net/member_illust.php?mode=medium&illust_id=65546468 3269 | /member_illust.php?mode=medium&illust_id=65546468 3270 | */ 3271 | changeTitle('↑'); 3272 | illust_url_list.shift(); //有时并未使用illust_url_list,但对空数组进行shift()是合法的 3273 | if (interrupt) { //判断任务是否已中断,目前只在tag搜索页有用到 3274 | allow_work = true; 3275 | return false; 3276 | } 3277 | if (quick) { // 快速下载时在这里提示一次 3278 | addOutputInfo('
    ' + xzlt('_开始获取作品页面')); 3279 | now_tips = outputInfo.innerHTML; 3280 | } 3281 | url = 'https://www.pixiv.net/ajax/illust/' + getIllustId(url); // 取出作品id,拼接出作品页api 3282 | 3283 | fetch(url) 3284 | .then(response => { 3285 | if (response.ok) { 3286 | return response.json(); 3287 | } else { 3288 | return Promise.reject({ 3289 | status: response.status, 3290 | statusText: response.statusText 3291 | }); 3292 | } 3293 | }) 3294 | .then(data => { 3295 | if (interrupt) { //这里需要再判断一次,因为ajax执行完毕是需要时间的 3296 | allow_work = true; 3297 | return false; 3298 | } 3299 | // 预设及获取图片信息 3300 | let jsInfo = data.body; 3301 | let id = jsInfo.illustId; 3302 | let fullWidth = parseInt(jsInfo.width); //原图宽度 3303 | let fullHeight = parseInt(jsInfo.height); //原图高度 3304 | let title = jsInfo.illustTitle; 3305 | let userid = jsInfo.userId; //画师id 3306 | let user = jsInfo.userName; //画师名字,如果这里获取不到,下面从 tag 尝试获取 3307 | let nowAllTagInfo = jsInfo.tags.tags; // tag列表 3308 | let nowAllTag = []; 3309 | if (nowAllTagInfo.length > 0) { 3310 | if (!user) { 3311 | user = nowAllTagInfo[0].userName ? nowAllTagInfo[0].userName : ''; // 这里从第一个tag里取出画师名字,如果没有 tag 那就获取不到画师名 3312 | } 3313 | nowAllTag = nowAllTagInfo.map(info => { 3314 | return info.tag; 3315 | }); 3316 | } 3317 | let bmk = jsInfo.bookmarkCount; // 收藏数 3318 | let ext = ''; //扩展名 3319 | let imgUrl = ''; 3320 | 3321 | // 检查宽高设置 3322 | let WH_check_result = checkSetWHOK(fullWidth, fullHeight); 3323 | 3324 | // 检查宽高比设置 3325 | let ratio_check_result = checkRatio(fullWidth, fullHeight); 3326 | 3327 | // 检查收藏数要求 3328 | let BMK_check_result = true; //预设为通过 3329 | if (is_set_filterBMK) { 3330 | if (bmk < filterBMK) { 3331 | BMK_check_result = false; 3332 | } 3333 | } 3334 | 3335 | // 检查只下载书签作品设置 3336 | let check_bookmark_result = true; 3337 | if (only_down_bmk) { 3338 | if (jsInfo.bookmarkData === null) { // 没有收藏 3339 | check_bookmark_result = false; // 检查不通过 3340 | } 3341 | } 3342 | 3343 | // 检查要排除的tag 其实page_type==9的时候在获取作品列表时就能获得tag列表,但为了统一,也在这里检查 3344 | let tag_check_result; // 储存tag检查结果 3345 | 3346 | // 检查要排除的tag,如果有多个,只需要满足一个即可 3347 | let tag_notNeed_isFound = false; 3348 | if (notNeed_tag.length > 0) { //如果设置了过滤tag 3349 | outerloop: //命名外圈语句 3350 | for (const tag of nowAllTag) { 3351 | for (const notNeed of notNeed_tag) { 3352 | if (tag === notNeed) { 3353 | tag_notNeed_isFound = true; 3354 | break outerloop; 3355 | } 3356 | } 3357 | } 3358 | } 3359 | 3360 | // 检查必须包含的tag,如果有多个,需要全部包含 3361 | if (!tag_notNeed_isFound) { //如果没有匹配到要排除的tag 3362 | if (need_tag.length > 0) { //如果设置了必须包含的tag 3363 | let tag_need_isFound = false; 3364 | let tag_need_matched = 0; 3365 | for (const tag of nowAllTag) { 3366 | for (const need of need_tag) { 3367 | if (tag === need) { 3368 | tag_need_matched++; 3369 | } 3370 | } 3371 | } 3372 | // 如果全部匹配 3373 | if (tag_need_matched === need_tag.length) { 3374 | tag_need_isFound = true; 3375 | } 3376 | tag_check_result = tag_need_isFound; 3377 | } else { //如果没有设置必须包含的tag,则通过 3378 | tag_check_result = true; 3379 | } 3380 | } else { //如果匹配到了要排除的tag,则不予通过 3381 | tag_check_result = false; 3382 | } 3383 | 3384 | // 总检查,要求上面条件全部通过 3385 | let total_check = tag_check_result && check_bookmark_result && WH_check_result && ratio_check_result && BMK_check_result; 3386 | 3387 | // 作品类型: 3388 | // 1 单图 3389 | // 2 多图 3390 | // 3 动图 3391 | let this_illust_type; 3392 | if (jsInfo.illustType === 0 || jsInfo.illustType === 1) { // 单图或多图,0插画1漫画2动图(1的如68430279) 3393 | if (jsInfo.pageCount === 1) { // 单图 3394 | this_illust_type = 1; 3395 | } else if (jsInfo.pageCount > 1) { // 多图 3396 | this_illust_type = 2; 3397 | } 3398 | } else if (jsInfo.illustType === 2) { // 动图 3399 | this_illust_type = 3; 3400 | } 3401 | 3402 | // 结合作品类型处理作品 3403 | if (this_illust_type === 1 && total_check) { //如果是单图 3404 | if (!notdown_type.includes('1')) { //如果没有排除单图 3405 | imgUrl = jsInfo.urls.original; 3406 | ext = imgUrl.split('.'); 3407 | ext = ext[ext.length - 1]; //扩展名 3408 | addImgInfo(id + '_p0', imgUrl, title, nowAllTag, user, userid, fullWidth, fullHeight, ext, bmk); 3409 | outputImgNum(); 3410 | } 3411 | } else if (this_illust_type !== 1 && total_check) { //单图以外的情况 3412 | if (this_illust_type === 3) { //如果是动图 3413 | if (!notdown_type.includes('3')) { //如果没有排除动图 3414 | // 动图的最终url如: 3415 | // https://i.pximg.net/img-zip-ugoira/img/2018/04/25/21/27/44/68401493_ugoira1920x1080.zip 3416 | imgUrl = jsInfo.urls.original.replace('img-original', 'img-zip-ugoira').replace('ugoira0', 'ugoira1920x1080').replace('jpg', 'zip').replace('png', 'zip'); 3417 | ext = 'ugoira'; //扩展名 3418 | addImgInfo(id, imgUrl, title, nowAllTag, user, userid, fullWidth, fullHeight, ext, bmk); 3419 | outputImgNum(); 3420 | } 3421 | } else { //多图作品 3422 | if (!notdown_type.includes('2')) { //如果没有排除多图 3423 | let pNo = jsInfo.pageCount; //P数 3424 | // 检查是否需要修改下载的张数。有效值为大于0并不大于总p数,否则下载所有张数 3425 | if (multiple_down_number > 0 && multiple_down_number <= pNo) { 3426 | pNo = multiple_down_number; 3427 | } 3428 | // 获取多p作品的原图页面 3429 | imgUrl = jsInfo.urls.original; 3430 | ext = imgUrl.split('.'); 3431 | ext = ext[ext.length - 1]; 3432 | for (let i = 0; i < pNo; i++) { 3433 | let now_url = imgUrl.replace('p0', 'p' + i); //拼接出每张图片的url 3434 | addImgInfo(id + '_p' + i, now_url, title, nowAllTag, user, userid, fullWidth, fullHeight, ext, bmk); 3435 | } 3436 | // 检查网址并添加到数组的动作执行完毕 3437 | outputImgNum(); 3438 | } 3439 | } 3440 | } 3441 | 3442 | if (page_type === 1 && !down_xiangguan) { // 在作品页内下载时,设置的want_page其实是作品数 3443 | if (want_page > 0) { 3444 | want_page--; 3445 | } 3446 | if (want_page === -1 || want_page > 0) { // 应该继续下载时 3447 | // 检查是否有下一个作品 3448 | // 在所有不为null的里面(可能有1-3个),取出key比当前作品id小的那一个,就是下一个 3449 | let user_illust = jsInfo.userIllusts; 3450 | let next_id; 3451 | for (const val of Object.values(user_illust)) { 3452 | if (val && val.illustId < id) { 3453 | next_id = val.illustId; 3454 | break; 3455 | } 3456 | } 3457 | if (next_id) { 3458 | getIllustPage('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + next_id); 3459 | } else { //没有剩余作品 3460 | allow_work = true; 3461 | allWorkFinished(); 3462 | } 3463 | } else { //没有剩余作品 3464 | allow_work = true; 3465 | allWorkFinished(); 3466 | } 3467 | } else { 3468 | if (illust_url_list.length > 0) { //如果存在下一个作品,则 3469 | getIllustPage(illust_url_list[0]); 3470 | } else { //没有剩余作品 3471 | ajax_threads_finished++; 3472 | if (ajax_threads_finished === ajax_for_illust_threads) { //如果所有并发请求都执行完毕 3473 | ajax_threads_finished = 0; //复位 3474 | allow_work = true; 3475 | allWorkFinished(); 3476 | } 3477 | } 3478 | } 3479 | }) 3480 | .catch(error => { 3481 | console.log(error); 3482 | illust_error(url); 3483 | switch (error.status) { 3484 | case 0: 3485 | console.log(xzlt('_作品页状态码0')); 3486 | break; 3487 | case 400: 3488 | console.log(xzlt('_作品页状态码400')); 3489 | break; 3490 | case 403: 3491 | console.log(xzlt('_作品页状态码403')); 3492 | break; 3493 | case 404: 3494 | console.log(xzlt('_作品页状态码404') + ' ' + url); 3495 | break; 3496 | default: 3497 | break; 3498 | } 3499 | }); 3500 | } 3501 | 3502 | // 测试图片url是否正确的函数。对于mode=big的作品和pixivision,可以拼接出图片url,只是后缀都是jpg的,所以要测试下到底是jpg还是png 3503 | function testExtName (url, length, img_info_data) { 3504 | test_suffix_finished = false; 3505 | // 初步获取到的后缀名都是jpg的 3506 | let ext = ''; 3507 | let testImg = new Image(); 3508 | testImg.src = url; 3509 | testImg.onload = () => nextStep(true); 3510 | testImg.onerror = () => nextStep(false); 3511 | 3512 | function nextStep (bool) { 3513 | if (bool) { 3514 | ext = 'jpg'; 3515 | } else { 3516 | url = url.replace('.jpg', '.png'); 3517 | ext = 'png'; 3518 | } 3519 | addImgInfo(img_info_data.id, url, img_info_data.title, img_info_data.tags, img_info_data.user, img_info_data.userid, img_info_data.fullWidth, img_info_data.fullHeight, ext, ''); 3520 | outputImgNum(); 3521 | if (length !== undefined) { //length参数只有在pixivision才会传入 3522 | test_suffix_no++; 3523 | if (test_suffix_no === length) { //如果所有请求都执行完毕 3524 | allWorkFinished(); 3525 | } 3526 | } 3527 | test_suffix_finished = true; 3528 | } 3529 | } 3530 | // mode=big类型在pc端可能已经消失了,但是移动端查看大图还是big https://www.pixiv.net/member_illust.php?mode=big&illust_id=66745241 3531 | // pixivision则是因为跨域问题,无法抓取p站页面 3532 | 3533 | // 重置下载区域的信息 3534 | function resetDownloadPanel () { 3535 | downloaded = 0; 3536 | document.querySelector('.downloaded').textContent = downloaded; 3537 | for (const el of document.querySelectorAll('.imgNum')) { 3538 | el.textContent = img_info.length; 3539 | } 3540 | for (const el of document.querySelectorAll('.download_fileName')) { 3541 | el.textContent = ''; 3542 | } 3543 | for (const el of document.querySelectorAll('.loaded')) { 3544 | el.textContent = '0/0'; 3545 | } 3546 | for (const el of document.querySelectorAll('.progress')) { 3547 | el.style.width = '0%'; 3548 | } 3549 | } 3550 | 3551 | // 抓取完毕 3552 | function allWorkFinished () { 3553 | // 检查快速下载状态 3554 | quiet_download = XZForm.setQuietDownload.checked; 3555 | if (test_suffix_finished) { // 检查后缀名的任务是否全部完成 3556 | down_xiangguan = false; // 解除下载相关作品的标记 3557 | if (page_type === 2) { // 在画师的列表页里 3558 | if (!loc_url.includes('bookmark.php')) { 3559 | // 如果是其他列表页,把作品数据按 id 倒序排列,id 大的在前面,这样可以先下载最新作品,后下载早期作品 3560 | img_info.sort(sortByProperty('id')); 3561 | } else { 3562 | // 如果是书签页,把作品数据反转,这样可以先下载收藏时间早的,后下载收藏时间近的 3563 | img_info.reverse(); 3564 | } 3565 | } 3566 | addOutputInfo('
    ' + xzlt('_获取图片网址完毕', img_info.length) + '
    '); 3567 | if (img_info.length === 0) { 3568 | addOutputInfo(xzlt('_没有符合条件的作品') + '

    '); 3569 | alert(xzlt('_没有符合条件的作品弹窗')); 3570 | allow_work = true; 3571 | return false; 3572 | } 3573 | // 显示输出结果完毕 3574 | addOutputInfo(xzlt('_抓取完毕') + '

    '); 3575 | if (!quiet_download && !quick) { 3576 | changeTitle('▶'); 3577 | } 3578 | now_tips = outputInfo.innerHTML; 3579 | // 重置下载区域 3580 | resetDownloadPanel(); 3581 | document.querySelector('.download_panel').style.display = 'block'; 3582 | // 显示输出区域 3583 | if (!quick) { 3584 | centerWrapShow(); 3585 | } 3586 | 3587 | // 快速下载时点击下载按钮 3588 | if (quick || quiet_download) { 3589 | setTimeout(function () { 3590 | document.querySelector('.startDownload').click(); 3591 | }, 200); 3592 | } 3593 | } else { //如果没有完成,则延迟一段时间后再执行 3594 | setTimeout(function () { 3595 | allWorkFinished(); 3596 | }, 1000); 3597 | } 3598 | } 3599 | 3600 | // 在抓取图片网址时,输出提示 3601 | function outputImgNum () { 3602 | outputInfo.innerHTML = now_tips + '
    ' + xzlt('_抓取图片网址的数量', img_info.length); 3603 | if (interrupt) { //如果任务中断 3604 | addOutputInfo('
    ' + xzlt('_抓取图片网址遇到中断') + '

    '); 3605 | } 3606 | } 3607 | 3608 | // 向中间面板添加按钮 3609 | function addCenterButton (tag = 'div', bg = xz_blue, text = '', attr = []) { 3610 | let e = document.createElement(tag); 3611 | e.style.backgroundColor = bg; 3612 | e.textContent = text; 3613 | for (const [key, value] of attr) { 3614 | e.setAttribute(key, value); 3615 | } 3616 | center_btn_wrap.appendChild(e); 3617 | return e; 3618 | } 3619 | 3620 | // 输出右侧按钮区域 3621 | function addRightButton () { 3622 | rightButton = document.createElement('div'); 3623 | rightButton.textContent = '↓'; 3624 | rightButton.id = 'rightButton'; 3625 | document.body.appendChild(rightButton); 3626 | // 绑定切换右侧按钮显示的事件 3627 | rightButton.addEventListener('click', () => { 3628 | centerWrapShow(); 3629 | }, false); 3630 | } 3631 | 3632 | // 显示提示 3633 | function XZTip (arg) { 3634 | let tip_text = this.dataset.tip; 3635 | if (!tip_text) { 3636 | return false; 3637 | } 3638 | if (arg.type === 1) { 3639 | XZTipEl.innerHTML = tip_text; 3640 | XZTipEl.style.left = arg.x + 30 + 'px'; 3641 | XZTipEl.style.top = arg.y - 30 + 'px'; 3642 | XZTipEl.style.display = 'block'; 3643 | } else if (arg.type === 0) { 3644 | XZTipEl.style.display = 'none'; 3645 | } 3646 | } 3647 | 3648 | // 添加中间的面板 3649 | function addCenterWarps () { 3650 | // 添加输出 url 列表、文件名列表的面板 3651 | let outputInfoWrap = document.createElement('div'); 3652 | document.body.appendChild(outputInfoWrap); 3653 | outputInfoWrap.outerHTML = ` 3654 |
    3655 |
    X
    3656 |
    ${xzlt('_输出信息')}
    3657 |
    3658 |
    3659 |
    ${xzlt('_复制')}
    3660 |
    3661 |
    3662 | `; 3663 | // 绑定关闭输出url区域的事件 3664 | document.querySelector('.outputUrlClose').addEventListener('click', () => { 3665 | document.querySelector('.outputInfoWrap').style.display = 'none'; 3666 | }); 3667 | // 绑定复制url的事件 3668 | document.querySelector('.outputUrlCopy').addEventListener('click', () => { 3669 | let range = document.createRange(); 3670 | range.selectNodeContents(document.querySelector('.outputInfoContent')); 3671 | window.getSelection().removeAllRanges(); 3672 | window.getSelection().addRange(range); 3673 | document.execCommand('copy'); 3674 | // 改变提示文字 3675 | document.querySelector('.outputUrlCopy').textContent = xzlt('_已复制到剪贴板'); 3676 | setTimeout(() => { 3677 | window.getSelection().removeAllRanges(); 3678 | document.querySelector('.outputUrlCopy').textContent = xzlt('_复制'); 3679 | }, 1000); 3680 | }); 3681 | 3682 | // 添加下载面板 3683 | centerWrap = document.createElement('div'); 3684 | document.body.appendChild(centerWrap); 3685 | centerWrap.outerHTML = ` 3686 |
    3687 |
    3688 |
    3689 | ${xzlt('_下载设置')} 3690 | 3691 | 3692 | 3693 |
    3694 |
    X
    3695 |
    3696 |
    3697 |

    ${xzlt('_扩展提示2')}

    3698 |
    3699 |
    3700 |

    3701 | 3702 | ${xzlt('_页数')} ? 3703 |     3704 | -1 或者大于 0 的数字 3705 | 3706 |

    3707 |

    3708 | ${xzlt('_筛选收藏数_center')} ? 3709 |      3710 |

    3711 |

    3712 | ${xzlt('_多p下载前几张')} ? 3713 | 3714 |

    3715 |

    3716 | ${xzlt('_筛选宽高的按钮文字')} ? 3717 | 3718 | 3719 | 3720 | 3721 |

    3722 |

    3723 | ${xzlt('_设置宽高比例')} ? 3724 | 3725 | 3726 | 3727 | 3728 |

    3729 |

    3730 | ${xzlt('_设置作品类型')} ? 3731 | 3732 | 3733 | 3734 |

    3735 |

    3736 | ${xzlt('_只下载已收藏')} ? 3737 | 3738 |

    3739 |

    3740 | ${xzlt('_必须含有tag')} ? 3741 | 3742 |

    3743 |

    3744 | ${xzlt('_不能含有tag')} ? 3745 | 3746 |

    3747 | 3751 |

    3752 | ${xzlt('_是否快速下载')} ? 3753 | 3754 |

    3755 |

    3756 | ${xzlt('_是否下载XMP')} ? 3757 | 3758 | What is XMP? 3759 |

    3760 |
    3761 |
    3762 | 3763 |
    3764 |

    ${xzlt('_设置命名规则3', '0')}

    3765 |

    3766 | ${xzlt('_设置下载线程')} ? 3767 | 3768 |

    3769 |

    3770 | ${xzlt('_设置文件名')} ? 3771 | 3772 |    3773 | 3775 |    3776 | 3788 |      3789 | ${xzlt('_查看标记的含义')} 3790 |

    3791 |

    3792 | ${xzlt('_设置文件夹名的提示').replace('
    ', '. ')} 3793 |
    3794 | {p_user} 3795 | ${xzlt('_文件夹标记_p_user')} 3796 |
    3797 | {p_uid} 3798 | ${xzlt('_文件夹标记_p_uid')} 3799 |
    3800 | {p_tag} 3801 | ${xzlt('_文件夹标记_p_tag')} 3802 |
    3803 | {p_title} 3804 | ${xzlt('_文件夹标记_p_title')} 3805 |
    3806 | {id} 3807 | ${xzlt('_可用标记1')} 3808 |
    3809 | {title} 3810 | ${xzlt('_可用标记2')} 3811 |
    3812 | {tags} 3813 | ${xzlt('_可用标记3')} 3814 |
    3815 | {user} 3816 | ${xzlt('_可用标记4')} 3817 |
    3818 | {userid} 3819 | ${xzlt('_可用标记6')} 3820 |
    3821 | {px} 3822 | ${xzlt('_可用标记7')} 3823 |
    3824 | {bmk} 3825 | ${xzlt('_可用标记8')} 3826 |
    3827 | {id_num} 3828 | ${xzlt('_可用标记9')} 3829 |
    3830 | {p_num} 3831 | ${xzlt('_可用标记10')} 3832 |
    3833 | ${xzlt('_可用标记5')} 3834 |

    3835 |

    3836 | ${xzlt('_添加标记名称')} ? 3837 | 3838 |     3839 | ${xzlt('_预览文件名')} 3840 |      3841 | ${xzlt('_如何建立文件夹')} 3842 |    3843 | ${xzlt('_ff不能建立文件夹')} 3844 |

    3845 |
    3846 |
    3847 |
    3848 |
    ${xzlt('_下载按钮1')}
    3849 |
    ${xzlt('_下载按钮2')}
    3850 |
    ${xzlt('_下载按钮3')}
    3851 |
    ${xzlt('_下载按钮4')}
    3852 |
    3853 |
    3854 |

    3855 | ${xzlt('_当前状态')} 3856 | ${xzlt('_未开始下载')} 3857 |

    3858 |
    3859 | ${xzlt('_下载进度:')} 3860 |
    3861 |
    3862 |
    3863 |
    3864 |
    3865 | 0 3866 | / 3867 | 0 3868 |
    3869 |
    3870 |
    3871 |
    3872 |
    3873 |

    ${xzlt('_下载线程:')}

    3874 |
      3875 |
    • 3876 |
      3877 |
      3878 |
      3879 |
      3880 |        ${xzlt('_已下载')}  0/0KB 3881 |
      3882 |
    • 3883 |
    3884 |
    3885 |
    3886 | 3887 |

    ${xzlt('_查看下载说明')}

    3888 |

    ${xzlt('_下载说明')}

    3889 |
    3890 | `; 3891 | 3892 | center_btn_wrap = document.querySelector('.centerWrap_btns_free'); 3893 | centerWrap = document.querySelector('.centerWrap'); 3894 | XZForm = document.querySelector('.XZForm'); 3895 | 3896 | // 显示隐藏扩展提示 3897 | if (isFirefox) { 3898 | document.querySelector('.chrome_extension').style.display = 'none'; 3899 | document.querySelector('.firefox_extension').style.display = 'block'; 3900 | } 3901 | 3902 | // 绑定下载区域的事件 3903 | document.querySelector('.centerWrap_close').addEventListener('click', centerWrapHide); 3904 | document.querySelector('.showFileNameResult').addEventListener('click', () => showOutputInfoWrap('name')); 3905 | document.querySelector('.showFileNameTip').addEventListener('click', () => toggle(document.querySelector('.fileNameTip'))); 3906 | document.querySelector('.showDownTip').addEventListener('click', () => toggle(document.querySelector('.downTip'))); 3907 | document.querySelector('.centerWrap_toogle_option').addEventListener('click', toggleOptionArea); 3908 | // 添加提示事件 3909 | XZTipEl = document.querySelector('.XZTipEl'); 3910 | let xztips = document.querySelectorAll('.xztip'); 3911 | for (const el of xztips) { 3912 | for (const ev of ['mouseenter', 'mouseleave']) { 3913 | el.addEventListener(ev, event => { 3914 | let e = event || window.event; 3915 | XZTip.call(el, { 3916 | 'type': (ev === 'mouseenter') ? 1 : 0, 3917 | 'x': e.clientX, 3918 | 'y': e.clientY 3919 | }); 3920 | }); 3921 | } 3922 | } 3923 | // 输入框获得焦点时自动选择文本 3924 | let center_inputs = XZForm.querySelectorAll('input[type=text]'); 3925 | for (const el of center_inputs) { 3926 | // 文件名例外 3927 | if (el.name !== 'fileNameRule') { 3928 | el.addEventListener('focus', function () { 3929 | this.select(); 3930 | }); 3931 | } 3932 | } 3933 | 3934 | appendValueToInput(XZForm.page_info_select, XZForm.fileNameRule); 3935 | appendValueToInput(XZForm.file_name_select, XZForm.fileNameRule); 3936 | 3937 | // 开始下载按钮 3938 | document.querySelector('.startDownload').addEventListener('click', () => { 3939 | if (download_started || img_info.length === 0) { // 如果正在下载中,或无图片,则不予处理 3940 | return false; 3941 | } 3942 | // 检查是否是可以下载的时间 3943 | let time1 = new Date().getTime() - can_start_time; 3944 | if (time1 < 0) { // 时间未到 3945 | setTimeout(() => { 3946 | document.querySelector('.startDownload').click(); // 到时间了再点击开始按钮 3947 | }, Math.abs(time1)); 3948 | return false; 3949 | } 3950 | // 重置一些条件 3951 | // 检查下载线程设置 3952 | let setThread = parseInt(XZForm.setThread.value); 3953 | if (setThread < 1 || setThread > 10 || isNaN(setThread)) { 3954 | download_thread = download_thread_deauflt; // 重设为默认值 3955 | } else { 3956 | download_thread = setThread; // 设置为用户输入的值 3957 | } 3958 | if (img_info.length < download_thread) { // 检查下载线程数 3959 | download_thread = img_info.length; 3960 | } 3961 | let centerWrap_down_list = document.querySelector('.centerWrap_down_list'); 3962 | centerWrap_down_list.style.display = 'block'; // 显示下载队列 3963 | let downloadBar = document.querySelectorAll('.downloadBar'); 3964 | if (downloadBar.length !== download_thread) { // 如果数量发生变化,重设进度条的数量 3965 | let result = ''; 3966 | for (let i = 0; i < download_thread; i++) { 3967 | result += downloadBar[0].outerHTML; 3968 | } 3969 | centerWrap_down_list.innerHTML = result; 3970 | } 3971 | downloadBar_list = document.querySelectorAll('.downloadBar'); 3972 | download_started = true; 3973 | if (!download_pause) { // 如果没有暂停,则重新下载,否则继续下载 3974 | resetDownloadPanel(); 3975 | } 3976 | download_pause = false; 3977 | download_stop = false; 3978 | 3979 | // 启动或继续 建立并发下载线程 3980 | addOutputInfo('
    ' + xzlt('_正在下载中') + '
    '); 3981 | if (page_type === 5) { // tag 搜索页按收藏数从高到低下载 3982 | img_info.sort(sortByProperty('bmk')); 3983 | } 3984 | for (let i = 0; i < download_thread; i++) { 3985 | if (i + downloaded < img_info.length) { 3986 | setTimeout(function () { 3987 | startDownload(i + downloaded, i); 3988 | }, 100 * (i + 1)); 3989 | } 3990 | } 3991 | document.querySelector('.down_status').textContent = xzlt('_正在下载中'); 3992 | download_a = document.querySelector('.download_a'); 3993 | }); 3994 | 3995 | // 暂停下载按钮 3996 | document.querySelector('.pauseDownload').addEventListener('click', () => { 3997 | if (img_info.length === 0) { 3998 | return false; 3999 | } 4000 | if (download_stop === true) { // 停止的优先级高于暂停。点击停止可以取消暂停状态,但点击暂停不能取消停止状态 4001 | return false; 4002 | } 4003 | if (download_pause === false) { 4004 | if (download_started) { // 如果正在下载中 4005 | download_pause = true; //发出暂停信号 4006 | download_started = false; 4007 | can_start_time = new Date().getTime() + pause_start_dealy; // 设置延迟一定时间后才允许继续下载 4008 | document.querySelector('.down_status').innerHTML = `${xzlt('_已暂停')}`; 4009 | addOutputInfo(xzlt('_已暂停') + '

    '); 4010 | } else { // 不在下载中的话不允许启用暂停功能 4011 | return false; 4012 | } 4013 | } 4014 | }); 4015 | 4016 | // 停止下载按钮 4017 | document.querySelector('.stopDownload').addEventListener('click', () => { 4018 | if (img_info.length === 0) { 4019 | return false; 4020 | } 4021 | if (download_stop === false) { 4022 | download_stop = true; 4023 | download_started = false; 4024 | can_start_time = new Date().getTime() + pause_start_dealy; // 设置延迟一定时间后才允许继续下载 4025 | document.querySelector('.down_status').innerHTML = `${xzlt('_已停止')}`; 4026 | addOutputInfo(xzlt('_已停止') + '

    '); 4027 | download_pause = false; 4028 | } 4029 | }); 4030 | 4031 | // 复制url按钮 4032 | document.querySelector('.copyUrl').addEventListener('click', () => showOutputInfoWrap('url')); 4033 | } 4034 | 4035 | // 把下拉框的选择项插入到文本框里 4036 | function appendValueToInput (form, to) { 4037 | form.addEventListener('change', function () { 4038 | if (this.value === 'default') { 4039 | return false; 4040 | } else { 4041 | // 把选择项插入到光标位置,并设置新的光标位置 4042 | let position = to.selectionStart; 4043 | to.value = to.value.substr(0, position) + this.value + to.value.substr(position, to.value.length); 4044 | to.selectionStart = position + this.value.length; 4045 | to.selectionEnd = position + this.value.length; 4046 | to.focus(); 4047 | // 保存命名规则 4048 | saveXZSetting('user_set_name', to.value); 4049 | } 4050 | }); 4051 | } 4052 | 4053 | // 显示中间区域 4054 | function centerWrapShow () { 4055 | centerWrap.style.display = 'block'; 4056 | rightButton.style.display = 'none'; 4057 | } 4058 | 4059 | // 隐藏中间区域 4060 | function centerWrapHide () { 4061 | centerWrap.style.display = 'none'; 4062 | rightButton.style.display = 'block'; 4063 | document.querySelector('.outputInfoWrap').style.display = 'none'; 4064 | } 4065 | 4066 | // 收起展开设置项 4067 | function toggleOptionArea () { 4068 | option_area_show = !option_area_show; 4069 | let xz_option_area = document.querySelectorAll('.xz_option_area'); 4070 | for (const iterator of xz_option_area) { 4071 | iterator.style.display = option_area_show ? 'block' : 'none'; 4072 | } 4073 | document.querySelector('.centerWrap_toogle_option').innerHTML = option_area_show ? '▲' : '▼'; 4074 | } 4075 | 4076 | // 使用快捷键切换显示隐藏 4077 | window.addEventListener('keydown', event => { 4078 | let e2 = event || window.event; 4079 | if (e2.altKey && e2.keyCode === 88) { 4080 | let now_display = centerWrap.style.display; 4081 | if (now_display === 'block') { 4082 | centerWrapHide(); 4083 | } else { 4084 | centerWrapShow(); 4085 | } 4086 | } 4087 | }, false); 4088 | 4089 | // 读取设置 4090 | function readXZSetting () { 4091 | xz_setting = localStorage.getItem('xz_setting'); 4092 | if (!xz_setting) { 4093 | // 设置为默认值。注意这里的 tag 设置是字符串形式 4094 | xz_setting = { 4095 | "multiple_down_number": 0, 4096 | "notdown_type": "", 4097 | "need_tag": "", 4098 | "notNeed_tag": "", 4099 | "display_cover": true, 4100 | "quiet_download": true, 4101 | "download_thread": 6, 4102 | "user_set_name": "{id}", 4103 | "tagName_to_fileName": true, 4104 | "download_XMPsidecar": false 4105 | }; 4106 | } else { 4107 | xz_setting = JSON.parse(xz_setting); 4108 | } 4109 | // 设置多图设置 4110 | let setPNo_input = XZForm.setPNo; 4111 | setPNo_input.value = xz_setting.multiple_down_number; 4112 | // 保存多图设置 4113 | setPNo_input.addEventListener('change', function () { 4114 | if (parseInt(this.value) >= 0) { 4115 | saveXZSetting('multiple_down_number', this.value); 4116 | } 4117 | }); 4118 | // 设置排除类型 4119 | xz_setting.notdown_type = xz_setting.notdown_type.replace('4', ''); // 某次升级取消了4,但如果旧版本留下了4就会导致问题,所以手动去掉。 4120 | for (let index = 0; index < xz_setting.notdown_type.length; index++) { 4121 | XZForm['setWorkType' + xz_setting.notdown_type[index]].checked = false; 4122 | } 4123 | // 保存排除类型 4124 | for (let index = 1; index < 4; index++) { 4125 | XZForm['setWorkType' + index].addEventListener('click', () => { 4126 | saveXZSetting('notdown_type', getNotDownType()); 4127 | }); 4128 | } 4129 | // 设置必须的 tag 4130 | let setTagNeed_input = XZForm.setTagNeed; 4131 | setTagNeed_input.value = xz_setting.need_tag; 4132 | // 保存必须的 tag设置 4133 | setTagNeed_input.addEventListener('change', function () { 4134 | saveXZSetting('need_tag', this.value); 4135 | }); 4136 | // 设置排除的 tag 4137 | let setTagNotNeed_input = XZForm.setTagNotNeed; 4138 | setTagNotNeed_input.value = xz_setting.notNeed_tag; 4139 | // 保存排除的 tag设置 4140 | setTagNotNeed_input.addEventListener('change', function () { 4141 | saveXZSetting('notNeed_tag', this.value); 4142 | }); 4143 | // 设置封面选项 4144 | let setDisplayCover_input = XZForm.setDisplayCover; 4145 | setDisplayCover_input.checked = xz_setting.display_cover; 4146 | // 保存封面选项 4147 | setDisplayCover_input.addEventListener('click', function () { 4148 | saveXZSetting('display_cover', this.checked); 4149 | }); 4150 | // 设置快速下载 4151 | let setQuietDownload_input = XZForm.setQuietDownload; 4152 | setQuietDownload_input.checked = xz_setting.quiet_download; 4153 | // 保存快速下载 4154 | setQuietDownload_input.addEventListener('click', function () { 4155 | saveXZSetting('quiet_download', this.checked); 4156 | }); 4157 | // 设置XMP下载 4158 | let setXMPDownload_input = XZForm.setXMPDownload; 4159 | setXMPDownload_input.checked = xz_setting.download_XMPsidecar; 4160 | // 保存XMP下载 4161 | setXMPDownload_input.addEventListener('click', function () { 4162 | saveXZSetting('download_XMPsidecar', this.checked); 4163 | }); 4164 | // 设置下载线程 4165 | let setThread_input = XZForm.setThread; 4166 | setThread_input.value = xz_setting.download_thread; 4167 | // 保存下载线程 4168 | setThread_input.addEventListener('change', function () { 4169 | if (this.value > 0 && this.value <= 10) { 4170 | saveXZSetting('download_thread', this.value); 4171 | } 4172 | }); 4173 | 4174 | // 设置文件命名规则 4175 | let fileNameRule_input = XZForm.fileNameRule; 4176 | if (page_type === 8) { 4177 | fileNameRule_input.value = '{id}'; // pixivision 里只有id可以使用 4178 | } else { 4179 | fileNameRule_input.value = xz_setting.user_set_name; 4180 | } 4181 | // 保存文件命名规则 4182 | fileNameRule_input.addEventListener('change', function () { 4183 | if (this.value !== '') { 4184 | saveXZSetting('user_set_name', this.value); 4185 | } else { 4186 | // 把下拉框恢复默认值 4187 | XZForm.file_name_select.value = XZForm.file_name_select.children[0].value; 4188 | } 4189 | }); 4190 | // 设置标记添加到文件名 4191 | let setTagNameToFileName_input = XZForm.setTagNameToFileName; 4192 | setTagNameToFileName_input.checked = xz_setting.tagName_to_fileName; 4193 | // 保存标记添加到文件名 4194 | setTagNameToFileName_input.addEventListener('click', function () { 4195 | saveXZSetting('tagName_to_fileName', this.checked); 4196 | }); 4197 | } 4198 | 4199 | // 储存设置 4200 | function saveXZSetting (key, value) { 4201 | xz_setting[key] = value; 4202 | localStorage.setItem('xz_setting', JSON.stringify(xz_setting)); 4203 | } 4204 | 4205 | // 隐藏不需要的选项 4206 | function hideNotNeedOption (no) { 4207 | for (const num of no) { 4208 | document.querySelector('.XZFormP' + num).style.display = 'none'; 4209 | } 4210 | } 4211 | 4212 | // 清除多图 4213 | function clearMultiple () { 4214 | addCenterButton('div', xz_red, xzlt('_清除多图作品'), [ 4215 | ['title', xzlt('_清除多图作品_title')] 4216 | ]).addEventListener('click', () => { 4217 | centerWrapHide(); 4218 | let allPicArea = document.querySelectorAll(tag_search_list_selector); 4219 | allPicArea.forEach(el => { 4220 | if (el.querySelector(tag_search_multiple_selector)) { 4221 | el.remove(); 4222 | } 4223 | }); 4224 | outputNowResult(); 4225 | }, false); 4226 | } 4227 | 4228 | // 清除动图 4229 | function clearUgoku () { 4230 | addCenterButton('div', xz_red, xzlt('_清除动图作品'), [ 4231 | ['title', xzlt('_清除动图作品_title')] 4232 | ]).addEventListener('click', () => { 4233 | centerWrapHide(); 4234 | let allPicArea = document.querySelectorAll(tag_search_list_selector); 4235 | allPicArea.forEach(el => { 4236 | if (el.querySelector(tag_search_gif_selector)) { 4237 | el.remove(); 4238 | } 4239 | }); 4240 | outputNowResult(); 4241 | }, false); 4242 | } 4243 | 4244 | // 手动删除 4245 | function deleteByClick () { 4246 | addCenterButton('div', xz_red, xzlt('_手动删除作品'), [ 4247 | ['title', xzlt('_手动删除作品_title')] 4248 | ]).addEventListener('click', function () { 4249 | del_work = !del_work; 4250 | // 给作品绑定删除属性 4251 | document.querySelectorAll(tag_search_list_selector).forEach(el => { 4252 | el.onclick = function (e) { 4253 | if (del_work) { 4254 | (e || window.event).preventDefault(); 4255 | this.remove(); 4256 | if (allow_work) { 4257 | outputNowResult(); 4258 | } 4259 | return false; 4260 | } 4261 | }; 4262 | }); 4263 | if (del_work) { 4264 | this.textContent = xzlt('_退出手动删除'); 4265 | setTimeout(() => { 4266 | centerWrapHide(); 4267 | }, 300); 4268 | } else { 4269 | this.textContent = xzlt('_手动删除作品'); 4270 | } 4271 | }); 4272 | } 4273 | 4274 | // 生成输出区域的内容,按 type 不同,输出不同的内容 4275 | function showOutputInfoWrap (type) { 4276 | if (img_info.length === 0) { 4277 | return false; 4278 | } 4279 | let result = ''; 4280 | if (type === 'url') { // 拷贝图片 url 4281 | result = img_info.reduce((total, now) => { 4282 | return total += (now.url + '
    '); 4283 | }, result); 4284 | } else if (type === 'name') { // 预览和拷贝图片名 4285 | result = img_info.reduce((total, now) => { 4286 | return total += (now.id + '.' + now.ext + ': ' + getFileName(now) + '
    '); // 在每个文件名前面加上它的原本的名字,方便用来做重命名 4287 | }, result); 4288 | } else { 4289 | return false; 4290 | } 4291 | document.querySelector('.outputInfoContent').innerHTML = result; 4292 | document.querySelector('.outputInfoWrap').style.display = 'block'; 4293 | } 4294 | 4295 | // 生成文件名,传入参数为图片信息 4296 | function getFileName (data) { 4297 | let result = XZForm.fileNameRule.value; 4298 | tagName_to_fileName = XZForm.setTagNameToFileName.checked; 4299 | // 为空时使用 {id} 4300 | result = result || '{id}'; 4301 | // 生成文件名 4302 | // 将序号部分格式化成 3 位数字。p 站投稿一次最多 200 张 4303 | // data.id = data.id.replace(/(\d.*p)(\d.*)/, (...str)=> { 4304 | // return str[1] + str[2].padStart(3, '0'); 4305 | // }); 4306 | let cfg = [{ 4307 | 'name': '{p_user}', 4308 | 'value': page_info.hasOwnProperty('p_user') ? getUserName() : '', 4309 | 'prefix': '', 4310 | 'safe': false 4311 | }, { 4312 | 'name': '{p_uid}', 4313 | 'value': page_info.hasOwnProperty('p_uid') ? getUserId() : '', 4314 | 'prefix': '', 4315 | 'safe': true 4316 | }, { 4317 | 'name': '{p_title}', 4318 | 'value': document.title.replace(/\[(0|↑|→|▶|↓|║|■|√| )\] /, '').replace(/^\(\d.*\) /, ''), // 去掉标题上的下载状态、消息数量提示 4319 | 'prefix': '', 4320 | 'safe': false 4321 | }, { 4322 | 'name': '{p_tag}', 4323 | 'value': page_info.p_tag ? page_info.p_tag : '', 4324 | 'prefix': '', 4325 | 'safe': false 4326 | }, { 4327 | 'name': '{id}', 4328 | 'value': data.id, // 值 4329 | 'prefix': '', // 添加的前缀 4330 | 'safe': true // 是否是安全的文件名。如果包含有一些特殊字符,就不安全,要进行替换 4331 | }, { 4332 | 'name': '{id_num}', 4333 | 'value': parseInt(data.id), 4334 | 'prefix': '', 4335 | 'safe': true 4336 | }, { 4337 | 'name': '{p_num}', 4338 | 'value': parseInt(/\d*$/.exec(data.id)), 4339 | 'prefix': '', 4340 | 'safe': true 4341 | }, { 4342 | 'name': '{title}', 4343 | 'value': data.title, 4344 | 'prefix': 'title_', 4345 | 'safe': false 4346 | }, { 4347 | 'name': '{user}', 4348 | 'value': data.user, 4349 | 'prefix': 'user_', 4350 | 'safe': false 4351 | }, { 4352 | 'name': '{userid}', 4353 | 'value': data.userid, 4354 | 'prefix': 'uid_', 4355 | 'safe': true 4356 | }, { 4357 | 'name': '{px}', 4358 | 'value': (function () { 4359 | if (result.includes('{px}') && data.fullWidth !== undefined) { 4360 | return data.fullWidth + 'x' + data.fullHeight; 4361 | } else { 4362 | return ''; 4363 | } 4364 | })(), 4365 | 'prefix': '', 4366 | 'safe': true 4367 | }, { 4368 | 'name': '{tags}', 4369 | 'value': data.tags.join(','), 4370 | 'prefix': 'tags_', 4371 | 'safe': false 4372 | }, { 4373 | 'name': '{bmk}', 4374 | 'value': data.bmk, 4375 | 'prefix': 'bmk_', 4376 | 'safe': false 4377 | }]; 4378 | 4379 | for (const item of cfg) { 4380 | if (result.includes(item.name)) { 4381 | if (item.value !== '' && item.value !== null) { // 只有当标记有值时才继续操作. 所以空的标记会原样保留 4382 | let once = String(item.value); 4383 | if (tagName_to_fileName) { 4384 | once = item.prefix + once; 4385 | } 4386 | if (!item.safe) { 4387 | once = once.replace(safe_fileName_rule, '_'); 4388 | } 4389 | result = result.replace(new RegExp(item.name, 'g'), once); // 将标记替换成最终值,如果有重复的标记,全部替换 4390 | } 4391 | } 4392 | } 4393 | 4394 | // 处理空值,不能做文件夹名的字符,连续的 '//'。 有时候两个斜线中间的字段是空值,最后就变成两个斜线挨在一起了 4395 | result = result.replace(/undefined/g, '').replace(safe_folder_rule, '_').replace(/\/{2,9}/, '/'); 4396 | // 去掉头尾的 / 4397 | if (result.startsWith('/')) { 4398 | result = result.replace('/', ''); 4399 | } 4400 | if (result.endsWith('/')) { 4401 | result = result.substr(0, result.length - 1); 4402 | } 4403 | 4404 | // 处理后缀名 4405 | result += '.' + data.ext; 4406 | if (data.ext === 'ugoira') { // 动图在最前面添加前缀 4407 | let index = result.lastIndexOf('/'); 4408 | result = result.substr(0, index + 1) + 'open_with_HoneyView-' + result.substr(index + 1, result.length); 4409 | } 4410 | 4411 | // 快速下载时,如果只有一个文件,则不建立文件夹 4412 | if (quick && img_info.length === 1) { 4413 | let index = result.lastIndexOf('/'); 4414 | result = result.substr(index + 1, result.length); 4415 | } 4416 | 4417 | // 脚本版的处理, 如果不可以建立文件夹,替换掉所有特殊符号 4418 | if (!allowFolder) { 4419 | result = result.replace(safe_fileName_rule, '_'); 4420 | } 4421 | 4422 | return result; 4423 | } 4424 | 4425 | // 开始下载 下载序号,要使用的显示队列的序号 4426 | function startDownload (downloadNo, downloadBar_no) { 4427 | changeTitle('↓'); 4428 | // 获取文件名 4429 | let fullFileName = getFileName(img_info[downloadNo]); 4430 | // 处理文件名长度 这里有个问题,因为无法预知浏览器下载文件夹的长度,所以只能预先设置一个预设值 4431 | fullFileName = fullFileName.substr(0, fileName_length); 4432 | downloadBar_list[downloadBar_no].querySelector('.download_fileName').textContent = fullFileName; 4433 | // let GM_XHR = 4434 | GM_xmlhttpRequest({ 4435 | method: 'GET', 4436 | url: img_info[downloadNo].url, 4437 | headers: { 4438 | referer: 'https://www.pixiv.net/' 4439 | }, 4440 | responseType: 'blob', 4441 | onabort: function () { }, 4442 | onprogress: function (xhr) { 4443 | // 当体积大于指定值时中断下载。这里只是一个判断,还需要处理后续操作。 4444 | // if (xhr.total>1000000) { 4445 | // GM_XHR.abort('too large'); 4446 | // } 4447 | // 显示下载进度 4448 | if (download_pause || download_stop) { 4449 | return false; 4450 | } 4451 | let loaded = parseInt(xhr.loaded / 1000); 4452 | let total = parseInt(xhr.total / 1000); 4453 | downloadBar_list[downloadBar_no].querySelector('.loaded').textContent = loaded + '/' + total; 4454 | downloadBar_list[downloadBar_no].querySelector('.progress').style.width = loaded / total * 100 + '%'; 4455 | }, 4456 | onload: function (xhr) { 4457 | if (download_pause || download_stop) { 4458 | return false; 4459 | } 4460 | let blobURL = window.URL.createObjectURL(xhr.response); // 返回的blob对象是整个response,而非responseText 4461 | // 点击下载按钮需要添加时间间隔 4462 | if (new Date().getTime() - click_time > time_interval) { 4463 | click_time = new Date().getTime(); 4464 | click_download_a(blobURL, fullFileName, downloadBar_no); 4465 | } else { 4466 | time_delay += time_interval; 4467 | setTimeout(() => { 4468 | click_download_a(blobURL, fullFileName, downloadBar_no); 4469 | }, time_delay); 4470 | } 4471 | } 4472 | }); 4473 | 4474 | download_XMPsidecar = XZForm.setXMPDownload.checked; 4475 | if (download_XMPsidecar) { 4476 | //在下载时生成XMP blob对象 4477 | let tags = img_info[downloadNo].tags; 4478 | 4479 | //加入作者进标签, |分隔在xnview中可以划分子tag 4480 | tags.push('USER|' + img_info[downloadNo].user); 4481 | //下载来源标记 4482 | tags.push('PIXIV-DOWNLOADER'); 4483 | //添加标题 4484 | tags.push('TITLE|' + img_info[downloadNo].title); 4485 | 4486 | //过滤Pixiv 杂乱的标签 4487 | //鬼滅の刃1000users入り => 1000users入り 4488 | const filter = /.*\D(\d+users入り)/; 4489 | 4490 | for (var i = 0; i < tags.length; i++) { 4491 | tags[i] = tags[i].toUpperCase(); 4492 | 4493 | if (filter.test(tags[i])) { 4494 | tags[i] = tags[i].replace(filter, '$1'); 4495 | } 4496 | } 4497 | 4498 | //Pixiv Tag是区分大小写的,这里去重 4499 | let uniTags = [...new Set(tags)]; 4500 | let xmpBlob = createSimpleXmpBlob(uniTags); 4501 | let xmpFilename = fullFileName + '.xmp'; 4502 | 4503 | // 下载XMP,因为是本地文件。没必要用click_download_a控制进程数量,和占用downloadBar 4504 | let a = document.createElement('a'); 4505 | let xmpUrl = window.URL.createObjectURL(xmpBlob); 4506 | a.href = xmpUrl; 4507 | a.download = xmpFilename; 4508 | document.body.appendChild(a); 4509 | a.click(); 4510 | addOutputInfo("
    XMP 下载完毕"); 4511 | //延时100ms后释放blog URL 4512 | setTimeout(() => { 4513 | window.URL.revokeObjectURL(xmpUrl); 4514 | },100); 4515 | 4516 | 4517 | } 4518 | 4519 | } 4520 | 4521 | //在本地创建XMP对象 4522 | function createSimpleXmpBlob(tags) { 4523 | if (tags.length <= 0) { return; } 4524 | 4525 | //创建XMP输出text 4526 | let outstr, tagfield = ''; 4527 | 4528 | tags.forEach(element => { 4529 | tagfield += '' + element + ''; 4530 | }); 4531 | 4532 | const xmpTemplateP1 = ''; 4533 | const xmpTemplateP2 = ''; 4534 | const xmpTemplateP3 = ''; 4535 | outstr = xmpTemplateP1 + tagfield + xmpTemplateP2 + tagfield + xmpTemplateP3; 4536 | 4537 | let blob = new Blob([outstr], { type: "text/xml" }); 4538 | return blob; 4539 | } 4540 | 4541 | // 下载到硬盘 4542 | function click_download_a (blobURL, fullFileName, downloadBar_no) { 4543 | if (new Date().getTime() - click_time < time_interval) { 4544 | // console.count('+1s'); // 此句输出加时的次数 4545 | setTimeout(() => { 4546 | click_download_a(blobURL, fullFileName, downloadBar_no); 4547 | }, time_interval); // 虽然设置了两次点击间隔不得小于time_interval,但实际执行过程中仍然有可能比time_interval小。间隔太小的话就会导致漏下。当间隔过小时补上延迟 4548 | return false; 4549 | } 4550 | // console.log(new Date().getTime() - click_time); // 此句输出两次点击的实际间隔 4551 | if (GM_info.downloadMode === 'native' || isFirefox) { // 默认的下载,不能建立文件夹 4552 | download_a.href = blobURL; 4553 | download_a.setAttribute('download', fullFileName); 4554 | download_a.click(); 4555 | window.URL.revokeObjectURL(blobURL); 4556 | } else if (GM_info.downloadMode === 'browser') { // 浏览器 API,可以建立文件夹 4557 | // 不能设置带 referer 的 headers,否则下载失败。所以还是没办法直接从原网址下载图片。 4558 | // conflictAction 目前也并不能生效,所以重复文件会有序号 4559 | GM_download({ 4560 | url: blobURL, 4561 | name: fullFileName, 4562 | onload: function () { 4563 | window.URL.revokeObjectURL(blobURL); 4564 | } 4565 | }); 4566 | } 4567 | 4568 | click_time = new Date().getTime(); 4569 | time_delay -= time_interval; 4570 | 4571 | if (time_delay < 0) { // 因为有多个线程,所以有可能把time_delay减小到0以下,这里做限制 4572 | time_delay += time_interval; 4573 | } 4574 | // 下载之后 4575 | downloaded++; 4576 | document.querySelector('.downloaded').textContent = downloaded; 4577 | document.querySelector('.progress1').style.width = downloaded / img_info.length * 100 + '%'; 4578 | if (downloaded === img_info.length) { // 如果所有文件都下载完毕 4579 | download_started = false; 4580 | quick = false; 4581 | download_stop = false; 4582 | download_pause = false; 4583 | downloaded = 0; 4584 | document.querySelector('.down_status').textContent = xzlt('_下载完毕'); 4585 | addOutputInfo(xzlt('_下载完毕') + '

    '); 4586 | changeTitle('√'); 4587 | } else { // 如果没有全部下载完毕 4588 | //如果已经暂停下载 4589 | if (download_pause) { 4590 | download_started = false; 4591 | quick = false; 4592 | changeTitle('║'); 4593 | return false; 4594 | } 4595 | 4596 | // 如果已经停止下载 4597 | if (download_stop) { 4598 | download_started = false; 4599 | quick = false; 4600 | changeTitle('■'); 4601 | return false; 4602 | } 4603 | 4604 | // 继续添加任务 4605 | if (downloaded + download_thread - 1 < img_info.length) { // 如果已完成的数量 加上 线程中未完成的数量,仍然没有达到文件总数 4606 | startDownload(downloaded + download_thread - 1, downloadBar_no); // 这里需要减一,就是downloaded本次自增的数字,否则会跳一个序号 4607 | } 4608 | } 4609 | } 4610 | 4611 | // 清空图片信息并重置输出区域,在重复抓取时使用 4612 | function resetResult () { 4613 | img_info = []; 4614 | centerWrapHide(); 4615 | document.querySelector('.outputInfoContent').innerHTML = ''; 4616 | download_started = false; 4617 | download_pause = false; 4618 | download_stop = false; 4619 | } 4620 | 4621 | // 根据页面类型不同,设置页数的提示 4622 | function changeWantPage () { 4623 | let setWantPageWrap = document.querySelector('.setWantPageWrap'); 4624 | let setWantPage = setWantPageWrap.querySelector('.setWantPage'); 4625 | let setWantPageTip1 = setWantPageWrap.querySelector('.setWantPageTip1'); 4626 | let setWantPageTip2 = setWantPageWrap.querySelector('.setWantPageTip2'); 4627 | switch (page_type) { 4628 | case 0: 4629 | setWantPageWrap.style.display = 'none'; 4630 | break; 4631 | case 1: 4632 | want_page = -1; 4633 | setWantPageTip1.textContent = xzlt('_个数'); 4634 | setWantPageTip1.dataset.tip = xzlt('_check_want_page_rule1_arg5') + '
    ' + xzlt('_相关作品大于0'); 4635 | setWantPageTip2.textContent = xzlt('_数字提示1'); 4636 | setWantPage.value = want_page; 4637 | break; 4638 | case 5: 4639 | want_page = 1000; 4640 | setWantPageTip1.textContent = xzlt('_页数'); 4641 | setWantPageTip1.dataset.tip = xzlt('_要获取的作品个数2'); 4642 | setWantPageTip2.textContent = '-1 - 1000'; 4643 | setWantPage.value = want_page; 4644 | break; 4645 | case 6: 4646 | setWantPageWrap.style.display = 'none'; 4647 | break; 4648 | case 7: 4649 | setWantPageWrap.style.display = 'none'; 4650 | break; 4651 | case 8: 4652 | setWantPageWrap.style.display = 'none'; 4653 | break; 4654 | case 9: 4655 | want_page = 100; 4656 | setWantPageTip1.textContent = xzlt('_个数'); 4657 | setWantPageTip1.dataset.tip = xzlt('_要获取的作品个数2'); 4658 | setWantPageTip2.textContent = '1 - 500'; 4659 | setWantPage.value = want_page; 4660 | break; 4661 | case 10: 4662 | want_page = 10; 4663 | setWantPageTip1.textContent = xzlt('_页数'); 4664 | setWantPageTip1.dataset.tip = xzlt('_check_want_page_rule1_arg8'); 4665 | set_max_num(); 4666 | setWantPageTip2.textContent = `1 - ${max_num}`; 4667 | setWantPage.value = want_page; 4668 | break; 4669 | case 11: 4670 | setWantPageWrap.style.display = 'none'; 4671 | break; 4672 | default: 4673 | want_page = -1; 4674 | setWantPageTip1.textContent = xzlt('_页数'); 4675 | setWantPageTip1.dataset.tip = xzlt('_check_want_page_rule1_arg5'); 4676 | setWantPageTip2.textContent = xzlt('_数字提示1'); 4677 | setWantPage.value = want_page; 4678 | break; 4679 | } 4680 | } 4681 | 4682 | // 获取一些当前页面的信息,用于文件名中 4683 | function getPageInfo () { 4684 | let page_info_select = XZForm.page_info_select; 4685 | // 添加文件夹可以使用的标记 4686 | page_info = {}; 4687 | page_info.p_title = ''; // 所有页面都可以使用 p_title 4688 | // 只有 1 和 2 可以使用画师信息 4689 | if (page_type === 1 || page_type === 2) { 4690 | // 一些信息可能需要从 dom 取得,在这里直接执行可能会出错,所以先留空 4691 | let add_tag_btn = document.getElementById('add_tag_btn'); 4692 | if (!loc_url.includes('bookmark.php')) { // 不是书签页 4693 | page_info.p_user = ''; 4694 | page_info.p_uid = ''; 4695 | if (add_tag_btn) { 4696 | add_tag_btn.style.display = 'none'; 4697 | } 4698 | } else { 4699 | if (add_tag_btn) { 4700 | add_tag_btn.style.display = 'inline-block'; 4701 | } 4702 | } 4703 | // 如果有 tag 则追加 tag 4704 | if (getQuery(loc_url, 'tag')) { 4705 | page_info.p_tag = decodeURIComponent(getQuery(loc_url, 'tag')); 4706 | } 4707 | } else if (page_type === 5) { 4708 | page_info.p_tag = decodeURIComponent(getQuery(loc_url, 'word')); 4709 | } 4710 | // 添加下拉选项 4711 | page_info_select.innerHTML = ''; 4712 | page_info_select.insertAdjacentHTML('beforeend', ''); 4713 | for (const key of Object.keys(page_info)) { 4714 | let option_html = ``; 4715 | page_info_select.insertAdjacentHTML('beforeend', option_html); 4716 | } 4717 | } 4718 | 4719 | // 判断 page_type,现在没有 3 、4、12、13 了 4720 | function checkPageType () { 4721 | old_page_type = page_type; 4722 | loc_url = location.href; 4723 | if (location.hostname === 'www.pixiv.net' && location.pathname === '/') { 4724 | page_type = 0; 4725 | } else if ((loc_url.includes('illust_id') || loc_url.includes('/artworks/')) && 4726 | !loc_url.includes('mode=manga') && 4727 | !loc_url.includes('bookmark_detail') && 4728 | !loc_url.includes('bookmark_add') && 4729 | !loc_url.includes('response.php')) { 4730 | page_type = 1; 4731 | } else if (!loc_url.includes('mode=manga&illust_id') && (/member_illust\.php\?.*id=/.test(loc_url) || loc_url.includes('member.php?id=') || loc_url.includes('bookmark.php'))) { 4732 | page_type = 2; 4733 | } else if (loc_url.includes('search.php?')) { 4734 | page_type = 5; 4735 | } else if (loc_url.includes('ranking_area.php') && loc_url !== 'https://www.pixiv.net/ranking_area.php') { 4736 | page_type = 6; 4737 | } else if (location.pathname === '/ranking.php') { 4738 | page_type = 7; 4739 | } else if (loc_url.includes('https://www.pixivision.net') && loc_url.includes('/a/')) { 4740 | page_type = 8; 4741 | } else if (loc_url.includes('bookmark_add.php?id=') || loc_url.includes('bookmark_detail.php?illust_id=') || loc_url.includes('recommended.php')) { 4742 | page_type = 9; 4743 | } else if (loc_url.includes('bookmark_new_illust') || loc_url.includes('new_illust.php') || loc_url.includes('new_illust_r18.php')) { 4744 | page_type = 10; 4745 | } else if (location.pathname === '/discovery') { 4746 | page_type = 11; 4747 | } else { 4748 | return false; 4749 | } 4750 | } 4751 | 4752 | checkPageType(); 4753 | 4754 | if (page_type !== undefined) { 4755 | addRightButton(); 4756 | addCenterWarps(); 4757 | changeWantPage(); 4758 | readXZSetting(); 4759 | getPageInfo(); 4760 | } 4761 | 4762 | // 作品页无刷新进入其他作品页面时 4763 | function listen1 () { 4764 | outputInfo.innerHTML = ''; // 切换页面时,清空输出区域 4765 | if (page_type === 1) { 4766 | initViewer(); // 调用图片查看器 4767 | } 4768 | // 还需要检查是否是动图,这个功能需要获取作品信息。为了避免重复获取,就使用 updateViewer() 里的入口,不再单独获取 4769 | } 4770 | 4771 | // 虽然是绑定在 page_type 2 上面,但 2 和 1 其实是同一个页面 4772 | if (page_type === 1 || page_type === 2) { 4773 | // pushState 判断从列表页进入作品页的情况,popstate 判断从作品页退回列表页的情况 4774 | ['pushState', 'popstate'].forEach(item => { 4775 | window.addEventListener(item, () => { 4776 | checkPageType(); // 当页面切换时,判断新页面的类型 4777 | changeWantPage(); 4778 | getPageInfo(); 4779 | listen1(); 4780 | // 当新旧页面的 page_type 不相同的时候 4781 | if (old_page_type !== page_type) { 4782 | center_btn_wrap.innerHTML = ''; // 清空原有的下载按钮 4783 | want_page = undefined; // 重置页数/个数设置 4784 | if (page_type === 1) { // 从 2 进入 1 4785 | PageType1(); 4786 | } else if (page_type === 2) { // 从 1 进入 2 4787 | PageType2(); 4788 | } 4789 | } 4790 | }); 4791 | }); 4792 | } 4793 | 4794 | // 执行 page_type 1 4795 | function PageType1 () { 4796 | getIllustInfo(); 4797 | 4798 | // 在右侧创建快速下载按钮 4799 | let quick_down_btn = document.createElement('div'); 4800 | quick_down_btn.id = 'quick_down_btn'; 4801 | quick_down_btn.textContent = '↓'; 4802 | quick_down_btn.setAttribute('title', xzlt('_快速下载本页')); 4803 | document.body.appendChild(quick_down_btn); 4804 | quick_down_btn.addEventListener('click', () => { 4805 | quick = true; 4806 | startGet(); 4807 | }, false); 4808 | 4809 | addCenterButton('div', xz_blue, xzlt('_从本页开始下载')).addEventListener('click', startGet); 4810 | 4811 | let down_xg_btn = addCenterButton('div', xz_blue, xzlt('_下载相关作品')); 4812 | down_xg_btn.addEventListener('click', () => { 4813 | set_requset_num(); 4814 | if (requset_number > 0) { 4815 | down_xiangguan = true; 4816 | startGet(); 4817 | } 4818 | }, false); 4819 | // 添加文件夹命名提醒 4820 | down_xg_btn.addEventListener('mouseenter', function () { 4821 | this.textContent = xzlt('_请留意文件夹命名'); 4822 | }); 4823 | down_xg_btn.addEventListener('mouseout', function () { 4824 | this.textContent = xzlt('_下载相关作品'); 4825 | }); 4826 | 4827 | download_gif_btn = addCenterButton('div', xz_green, xzlt('_转换为 GIF')); 4828 | download_gif_btn.style.display = 'none'; 4829 | download_gif_btn.addEventListener('click', () => { 4830 | centerWrapHide(); 4831 | // 下载动图 4832 | fetch(gif_src) 4833 | .then(res => res.blob()) 4834 | .then(data => { 4835 | zip_file = data; 4836 | }); 4837 | changeTitle('↑'); 4838 | insertOutputInfo(); 4839 | addOutputInfo('
    ' + xzlt('_准备转换')); 4840 | checkCanConvert(); 4841 | }, false); 4842 | 4843 | quickBookmark(); 4844 | initViewer(); 4845 | 4846 | // 创建 gif 图片列表 4847 | gif_img_list = document.createElement('div'); 4848 | gif_img_list.style.display = 'none'; 4849 | document.body.appendChild(gif_img_list); 4850 | } 4851 | 4852 | // 执行 page_type 2 4853 | function PageType2 () { 4854 | 4855 | addCenterButton('div', xz_blue, xzlt('_开始抓取'), [ 4856 | ['title', xzlt('_开始抓取') + xzlt('_默认下载多页')] 4857 | ]).addEventListener('click', startGet); 4858 | 4859 | // 在书签页面隐藏只要书签选项 4860 | if (loc_url.includes('bookmark.php')) { 4861 | hideNotNeedOption([11]); 4862 | } 4863 | 4864 | // 删除快速下载按钮 4865 | let quick_down_btn = document.getElementById('quick_down_btn'); 4866 | if (quick_down_btn) { 4867 | quick_down_btn.remove(); 4868 | } 4869 | 4870 | // 如果存在 token,则添加“添加 tag”的按钮 4871 | if (getToken()) { 4872 | let add_tag_btn = addCenterButton('div', xz_blue, xzlt('_添加tag'), [ 4873 | ['title', xzlt('_添加tag')] 4874 | ]); 4875 | add_tag_btn.id = 'add_tag_btn'; 4876 | if (!loc_url.includes('bookmark.php')) { 4877 | add_tag_btn.style.display = 'none'; 4878 | } 4879 | add_tag_btn.addEventListener('click', readyAddTag); 4880 | } 4881 | } 4882 | 4883 | if (page_type === 0) { //0.index 首页 4884 | 4885 | let down_id_input, 4886 | id_value = []; 4887 | 4888 | // 添加输入id的按钮 4889 | let down_id_button = addCenterButton('div', xz_blue, xzlt('_输入id进行下载'), [ 4890 | ['id', 'down_id_button'] 4891 | ]); 4892 | down_id_button.dataset.ready = 'false'; //是否准备好了 4893 | down_id_button.addEventListener('click', () => { 4894 | illust_url_list = []; //每次开始下载前重置作品的url列表 4895 | if (down_id_button.dataset.ready === 'false') { //还没准备好 4896 | down_id_input.style.display = 'block'; 4897 | centerWrapHide(); 4898 | document.documentElement.scrollTop = 0; 4899 | } else { 4900 | //检查id 4901 | id_value = down_id_input.value.split('\n'); 4902 | id_value.forEach(id => { 4903 | let now_id = parseInt(id); 4904 | if (isNaN(now_id) || now_id < 22 || now_id > 99999999) { //如果id不是数字,或者处于非法区间 4905 | illust_url_list = []; //清空结果 4906 | alert(xzlt('_id不合法')); 4907 | return false; 4908 | } else { 4909 | //拼接作品的url 4910 | illust_url_list.push('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + id); 4911 | } 4912 | }); 4913 | addOutputInfo(xzlt('_任务开始0')); 4914 | startGet(); //进入下载流程 4915 | } 4916 | }, false); 4917 | 4918 | //用于输入id的输入框 4919 | down_id_input = document.createElement('textarea'); 4920 | down_id_input.id = 'down_id_input'; 4921 | down_id_input.setAttribute('placeholder', xzlt('_输入id进行下载的提示文字')); 4922 | insertToHead(down_id_input); 4923 | down_id_input.addEventListener('change', () => { // 当输入框内容改变时检测 4924 | if (down_id_input.value !== '') { //非空值 4925 | down_id_button.dataset.ready = 'true'; 4926 | centerWrapShow(); 4927 | down_id_button.textContent = xzlt('_开始抓取'); 4928 | } else { 4929 | down_id_button.dataset.ready = 'false'; 4930 | centerWrapHide(); 4931 | down_id_button.textContent = xzlt('_输入id进行下载'); 4932 | } 4933 | }); 4934 | } 4935 | if (page_type === 1) { //1. illust 作品页内页 4936 | 4937 | PageType1(); 4938 | 4939 | } else if (page_type === 2) { //2.user_page 个人资料页以及收藏页 4940 | 4941 | PageType2(); 4942 | 4943 | } else if (page_type === 5) { //5.tagsearch 4944 | 4945 | tag_search_lv1_selector = '#js-mount-point-search-result-list'; 4946 | tag_search_list_selector = '.JoCpVnw'; 4947 | // 因为tag搜索页新版将结果储存在一个div标签的属性里,而不是直接输出到html,但我们需要呈现html,所以需要模拟生成的元素 4948 | tag_search_new_html = ` 4949 |
    4950 |
    4951 |
    4952 | 4953 | 4954 | 4955 | 4956 | 4957 |
    4958 |
    4959 |
    4960 |
    4961 |
    4962 | 4970 |
    4971 |
    4972 |
    4973 |
    4974 |
    4975 | 4995 |
    4996 |
    4997 |
    4998 | `; 4999 | xz_multiple_html = `
    xz_pageCount
    `; 5000 | xz_gif_html = `
    `; 5001 | 5002 | base_url = loc_url.split('&p=')[0] + '&p='; 5003 | getNowPageNo(); 5004 | document.getElementById('js-react-search-mid').style.minHeight = 'auto'; //原来的最小高度是500,改成auto以免搜索时这部分空白 5005 | XZForm.setFavNum.value = 1000; // tag 搜索页默认收藏数设置为 1000 5006 | document.querySelector('.XZFormP9').style.display = 'block'; // 显示封面图设置 5007 | 5008 | // 添加快速筛选功能 5009 | let nowTag = document.querySelector('.column-title a').textContent.split(' ')[0]; 5010 | let favNums = ['100users入り', '500users入り', '1000users入り', '3000users入り', '5000users入り', '10000users入り', '20000users入り', '30000users入り', '50000users入り']; //200和2000的因为数量太少,不添加。40000的也少 5011 | let fastScreenArea = document.createElement('div'); 5012 | fastScreenArea.className = 'fastScreenArea'; 5013 | let insetParent = document.querySelector('._unit'); 5014 | insetParent.insertBefore(fastScreenArea, insetParent.querySelector('#js-react-search-top')); 5015 | let search_mode = ''; // 判断当前搜索模式,默认的“全部”模式不需要做处理 5016 | if (loc_url.includes('&mode=r18')) { 5017 | search_mode = '&mode=r18'; 5018 | } else if (loc_url.includes('&mode=safe')) { 5019 | search_mode = '&mode=safe'; 5020 | } 5021 | let order_mode = ''; // 判断当前排序方式 5022 | if (loc_url.includes('&order=date_d')) { // 按最新排序 5023 | order_mode = '&order=date_d'; 5024 | } else if (loc_url.includes('&order=date')) { // 按旧排序 5025 | order_mode = '&order=date'; 5026 | } 5027 | fastScreenArea.innerHTML = favNums.reduce((result, cur) => { 5028 | return result += `${cur}`; 5029 | }, ''); 5030 | 5031 | addCenterButton('div', xz_green, xzlt('_开始筛选'), [ 5032 | ['title', xzlt('_开始筛选_title')] 5033 | ]).addEventListener('click', () => { 5034 | if (interrupt) { 5035 | interrupt = false; 5036 | } 5037 | startGet(); 5038 | }, false); 5039 | 5040 | addCenterButton('div', xz_green, xzlt('_在结果中筛选'), [ 5041 | ['title', xzlt('_在结果中筛选_title')] 5042 | ]).addEventListener('click', () => { 5043 | let allPicArea = document.querySelectorAll(tag_search_list_selector); 5044 | let want_favorite_number2 = prompt(xzlt('_在结果中筛选弹窗'), '2000'); 5045 | if (!want_favorite_number2) { 5046 | return false; 5047 | } else if (isNaN(Number(want_favorite_number2)) || ~~Number(want_favorite_number2) <= 0) { 5048 | alert(xzlt('_参数不合法1')); 5049 | return false; 5050 | } else { 5051 | want_favorite_number2 = ~~Number(want_favorite_number2); 5052 | } 5053 | allPicArea.forEach(el => { 5054 | if (parseInt(el.querySelector('._ui-tooltip').textContent) < want_favorite_number2) { //必须限制序号0,不然对图片的回应数也会连起来 5055 | el.style.display = 'none'; //这里把结果中不符合二次过滤隐藏掉,而非删除 5056 | } else { 5057 | el.style.display = 'inline-flex'; 5058 | } 5059 | }); 5060 | outputNowResult(); 5061 | centerWrapHide(); 5062 | }, false); 5063 | 5064 | addCenterButton('div', xz_red, xzlt('_中断当前任务'), [ 5065 | ['title', xzlt('_中断当前任务_title')] 5066 | ]).addEventListener('click', () => { 5067 | interrupt = true; 5068 | if (!allow_work) { 5069 | addOutputInfo('
    ' + xzlt('_当前任务已中断') + '

    '); 5070 | allow_work = true; 5071 | } 5072 | centerWrapHide(); 5073 | }, false); 5074 | 5075 | clearMultiple(); 5076 | 5077 | clearUgoku(); 5078 | 5079 | deleteByClick(); 5080 | 5081 | addCenterButton('div', xz_blue, xzlt('_下载当前作品'), [ 5082 | ['title', xzlt('_下载当前作品_title')] 5083 | ]).addEventListener('click', getListPage2); 5084 | 5085 | } else if (page_type === 6) { //6.ranking_area 5086 | 5087 | addCenterButton('div', xz_blue, xzlt('_下载本页作品'), [ 5088 | ['title', xzlt('_下载本页作品_title')] 5089 | ]).addEventListener('click', startGet); 5090 | 5091 | } else if (page_type === 7) { //7.ranking_else 5092 | 5093 | if (location.search === '') { // 直接获取json数据 5094 | base_url = loc_url + '?format=json&p='; 5095 | } else { 5096 | base_url = loc_url + '&format=json&p='; 5097 | } 5098 | 5099 | startpage_no = 1; //从第一页(部分)开始抓取 5100 | listPage_finished = 0; //已经向下抓取了几页(部分) 5101 | 5102 | // 设置页数。排行榜页面一页有50张作品,当页面到达底部时会加载下一页 5103 | if (base_url.includes('r18g')) { // r18g只有1个榜单,固定1页 5104 | part_number = 1; 5105 | } else if (base_url.includes('_r18')) { // r18模式,这里的6是最大值,有的排行榜并没有6页 5106 | part_number = 6; 5107 | } else { //普通模式,这里的10也是最大值。如果实际没有10页,则在检测到404页面的时候停止抓取下一页 5108 | part_number = 10; 5109 | } 5110 | 5111 | addCenterButton('div', xz_blue, xzlt('_下载本排行榜作品'), [ 5112 | ['title', xzlt('_下载本排行榜作品_title')] 5113 | ]).addEventListener('click', startGet); 5114 | 5115 | } else if (page_type === 8) { //8.pixivision 5116 | 5117 | let type = document.querySelector('a[data-gtm-action=ClickCategory]').getAttribute('data-gtm-label'); 5118 | if (type == 'illustration' || type == 'manga' || type == 'cosplay') { //在插画、漫画、cosplay类型的页面上创建下载功能 5119 | 5120 | addCenterButton('div', xz_blue, xzlt('_下载该页面的图片')).addEventListener('click', () => { 5121 | resetResult(); 5122 | insertOutputInfo(); 5123 | changeTitle('↑'); 5124 | let imageList = []; //图片元素的列表 5125 | if (type == 'illustration') { // 针对不同的类型,选择器不同 5126 | imageList = document.querySelectorAll('.am__work__main img'); 5127 | let urls = Array.from(imageList).map(el => { 5128 | return el.src.replace('c/768x1200_80/img-master', 'img-original').replace('_master1200', ''); 5129 | }); 5130 | test_suffix_no = 0; 5131 | urls.forEach((url, index) => { 5132 | let id = url.split('/'); 5133 | id = id[id.length - 1].split('.')[0]; //作品id 5134 | setTimeout(testExtName(url, urls.length, { 5135 | id: id, 5136 | title: '', 5137 | tags: [], 5138 | user: '', 5139 | userid: '', 5140 | fullWidth: '', 5141 | fullHeight: '' 5142 | }), index * ajax_for_illust_delay); 5143 | }); 5144 | } else { 5145 | if (type == 'manga') { 5146 | imageList = document.querySelectorAll('.am__work__illust'); 5147 | } else if (type == 'cosplay') { 5148 | imageList = document.querySelectorAll('.fab__image-block__image img'); 5149 | } 5150 | Array.from(imageList).forEach(el => { // 把图片url添加进数组 5151 | let imgUrl = el.src; 5152 | if (imgUrl !== 'https://i.pximg.net/imgaz/upload/20170407/256097898.jpg') { // 跳过Cure的logo图片 5153 | let id = imgUrl.split('/'); 5154 | id = id[id.length - 1].split('.')[0]; //作品id 5155 | let ext = imgUrl.split('.'); 5156 | ext = ext[ext.length - 1]; //扩展名 5157 | addImgInfo(id, imgUrl, '', [], '', '', '', '', ext, ''); 5158 | } 5159 | 5160 | }); 5161 | allWorkFinished(); 5162 | } 5163 | }, false); 5164 | } 5165 | 5166 | hideNotNeedOption([1, 2, 3, 4, 5, 6, 7, 11, 13]); 5167 | 5168 | } else if (page_type === 9) { //9.bookmark_add 5169 | // bookmark_add的页面刷新就变成bookmark_detail了; recommended.php是首页的“为你推荐”栏目 5170 | // 在收藏后的相似图片页面,可以获得收藏数,如 https://www.pixiv.net/bookmark_detail.php?illust_id=63148723 5171 | 5172 | let text, attr; 5173 | if (loc_url.includes('recommended.php')) { 5174 | text = xzlt('_下载推荐图片'); 5175 | attr = [ 5176 | ['title', xzlt('_下载推荐图片_title')] 5177 | ]; 5178 | } else { 5179 | text = xzlt('_下载相似图片'); 5180 | } 5181 | addCenterButton('div', xz_blue, text, attr).addEventListener('click', () => { 5182 | set_requset_num(); 5183 | if (requset_number > 0) { 5184 | startGet(); 5185 | } 5186 | }, false); 5187 | 5188 | } else if (page_type === 10) { //10.bookmark_new_illust and new_illust 关注的人的新作品 以及 大家的新作品 5189 | 5190 | if (loc_url.includes('/bookmark_new_illust')) { 5191 | list_is_new = true; 5192 | tag_search_lv1_selector = '#js-mount-point-latest-following'; // 在 关注的人 里使用 5193 | tag_search_list_selector = '.JoCpVnw'; 5194 | } 5195 | 5196 | //列表页url规则 5197 | if (!loc_url.includes('type=')) { //如果没有type标志,说明是在“综合”分类的第一页,手动加上分类 5198 | base_url = loc_url + '?type=all'.split('&p=')[0] + '&p='; 5199 | } else { 5200 | base_url = loc_url.split('&p=')[0] + '&p='; 5201 | } 5202 | 5203 | set_max_num(); // 页数上限 5204 | getNowPageNo(); 5205 | 5206 | addCenterButton('div', xz_blue, xzlt('_从本页开始下载'), [ 5207 | ['title', xzlt('_下载大家的新作品')] 5208 | ]).addEventListener('click', startGet); 5209 | 5210 | } else if (page_type === 11) { //11.discover 发现 5211 | // 其实发现页面和9收藏后的推荐页面一样,先获取列表再下载。但是发现页面有个特点是每次获取的数据是不同的,如果再请求一次列表数据,那么下载到的图片和本次加载的图片就不一样了。所以这里改用直接下载左侧已有作品 5212 | tag_search_list_selector = '._2RNjBox'; // 发现作品的已有作品 5213 | 5214 | addCenterButton('div', xz_blue, xzlt('_下载当前作品'), [ 5215 | ['title', xzlt('_下载当前作品_title')] 5216 | ]).addEventListener('click', startGet); 5217 | 5218 | clearMultiple(); 5219 | 5220 | clearUgoku(); 5221 | 5222 | deleteByClick(); 5223 | 5224 | addCenterButton('div', xz_red, xzlt('_清空作品列表'), [ 5225 | ['title', xzlt('_清空作品列表_title')] 5226 | ]).addEventListener('click', () => { 5227 | document.querySelectorAll(tag_search_list_selector).remove(); 5228 | centerWrapHide(); 5229 | }, false); 5230 | } 5231 | -------------------------------------------------------------------------------- /log.md: -------------------------------------------------------------------------------- 1 | ## 4.5.0 2 | 3 | 在排除类型里增加了“排除已收藏作品”的功能 4 | 5 | 0 在内页处理 √ 6 | 7 | 1 在内页处理 √ 8 | 9 | 2 列表页-列表页1 √ 10 | 11 | 3 tag页-列表页1 √ 12 | 13 | 4 收藏页-列表页1 √ 14 | 15 | 5 tag搜索页-列表页2 √ 16 | 17 | 6 地区排行榜-列表页3 √ 18 | 19 | 7 其他排行榜-列表页4 √ 20 | 21 | 8 pixivision-不处理 √ 22 | 23 | 9 bookmark_add-在内页处理 √ 24 | 25 | 10 大家的新作品-列表页1 √ 26 | 27 | 11 发现-不处理 √ 28 | 29 | 12 showcase 特辑-不处理 √ 30 | 31 | 13 响应关联作品-不处理 √ 32 | 33 | ## 4.5.2 34 | 35 | 1. “关注的新作品”(/bookmark_new_illust.php)改版了,列表页规则和tag搜索页一样了。 36 | 37 | tag搜索页的模式目前有3个页面在使用: 38 | 39 | - tag搜索页 40 | - 发现 discovery 41 | - 关注的新作品 42 | 43 | 2. “为你推荐”(/recommended.php)合并到发现(/discovery)功能了,但是代码里仍然先保存相关内容。 44 | 45 | 3. 另外tag搜索页新版刚出的时候是新旧版混合,代码里也对此作了判断。现在看来应该全部换成新版,没有旧版了。但是代码也先保留吧。 46 | 47 | ## 4.5.5 48 | 49 | chrome浏览器进行下载时,会把图片的blob对象在当前标签页打开,不清楚具体原因。给用于下载的a标签添加了 target="_blank"属性解决了。之前没有target属性也可以直接下载的,现在挺奇怪。 50 | 51 | ## 4.6.0 52 | 53 | 增加了multiple_down_number参数,可以设置多图作品只下载前几张。默认未限制。 54 | 55 | 修改后需要刷新页面才会生效,不需要使用时可以改回0。 56 | 57 | 有时候这是很有用的,有很多的多图作品,只有第一张图是彩色的,后面的图都是黑白的。把multiple_down_number设置为1就可以只下载第一张彩图了。 58 | 59 | 另外,最近我发现地区排行榜(/ranking_area.php)已经不在首页出现了。 60 | 61 | 一个已知的问题: 62 | 63 | 在[每日排行榜](https://www.pixiv.net/ranking.php?mode=daily_r18),有可能出现最后一张图没抓取完的时候,就提示抓取。这个问题不会影响实际下载的文件数量。 64 | 65 | ## 4.7.0 66 | 67 | 增加对pixiv特辑(showcase)的适配; 68 | 69 | bug修复。 70 | 71 | 其他情况: 72 | 73 | pixivision在首页原来有4个插画特辑,现在被pixiv自己的特辑(showcase)取代了。在首页只剩下两个推荐特辑的位置,这种类型(推荐)没有做适配。 74 | 75 | pixiv特辑(showcase)有[插画](https://www.pixiv.net/showcase/c/illustration/)和[漫画](https://www.pixiv.net/showcase/c/manga/)等分类,本工具只下载插画。漫画的话可以点击进入插画页自行下载。 76 | 77 | 此外,pixiv特辑滚动到底部时,会加载相似的其他特辑,页面url也会发生改变。本工具下载时会下载当前查看的特辑。 78 | 79 | ## 4.7.1 80 | 81 | 修正的问题: 82 | 83 | 1.大家的新作品里,有按类型分类的页面,之前都是按“综合”处理的,现在可以正确按当前类型获取了。 84 | 85 | 2.之前无法正常下载关注的新作品的r18分类,现在已经修复。 86 | 87 | 原本想给排行榜增加手动删除按钮,但是做了之后又去掉了。因为排行榜是分多个部分的,所以获取的时候要通过ajax抓取,在页面上删除没有意义。 88 | 89 | ## 4.7.2 90 | 91 | 修复了在tag搜索页里,搜索中断之后,下载时图片网址可能数量异常的问题。 92 | 93 | ## 4.8.0 94 | 95 | - tag搜索页的快速搜索功能可以保持当前搜索模式(全部/普通/R-18)和排序模式 96 | 97 | - 优化下载排行榜作品的代码 98 | 99 | - 适应pixivision改版 100 | 101 | - 增加了对“响应关联作品”的适配 102 | 103 | ps0:pixivision改版后,插画页面的头图不是单独的图片了,所以不用单独获取了。 104 | 105 | ps1:响应关联作品大部分都比较少,我还没看到超过一页的。目前按作品列表页进行处理,默认下载所有页面。如果有发现分页的话可以告诉我。 106 | 107 | ps2:其他排行榜里获取页面时,之前的代码是通过分析dom获得作品数据的。最近发现可以直接获取到json数据了,但是缺少扩展名信息。所以现在只是从json里取得作品页url,其他信息仍然去抓取作品页。 108 | 109 | [json示例]https://www.pixiv.net/ranking.php?mode=monthly&content=illust&p=1&format=json 110 | 111 | ### 截止2018/2/21,各个排行榜的综合类型的页数(每个排行榜的细分类型的页数和综合不一定相同): 112 | 113 | **普通的有7种排行榜** 114 | 115 | - (今日:10页)[https://www.pixiv.net/ranking.php?mode=daily] 116 | 117 | - (本周:10页)[https://www.pixiv.net/ranking.php?mode=weekly] 118 | 119 | - (本月:10页)[https://www.pixiv.net/ranking.php?mode=monthly] 120 | 121 | - (新人:6页)[https://www.pixiv.net/ranking.php?mode=rookie] 122 | 123 | - (原创:6页)[https://www.pixiv.net/ranking.php?mode=original] 124 | 125 | - (受男性欢迎:10页)[https://www.pixiv.net/ranking.php?mode=male] 126 | 127 | - (受女性欢迎:10页)[https://www.pixiv.net/ranking.php?mode=female] 128 | 129 | **R-18有4种排行榜** 130 | 131 | - (今日r18:2页)[https://www.pixiv.net/ranking.php?mode=daily_r18] 132 | 133 | - (本周r18:2页)[https://www.pixiv.net/ranking.php?mode=weekly_r18] 134 | 135 | - (受男性欢迎r18:6页)[https://www.pixiv.net/ranking.php?mode=male_r18] 136 | 137 | - (受女性欢迎r18:6页)[https://www.pixiv.net/ranking.php?mode=female_r18] 138 | 139 | **R-18G只有一种排行榜** 140 | 141 | - (r18g:1页)[https://www.pixiv.net/ranking.php?mode=r18g] 142 | 143 | ## 5.0.0 144 | 145 | bug修复和代码优化。 146 | 147 | ps1:模板字符串虽然好用,但如果原来的语句里的运算步骤复杂的话,这部分还是用加号拼接比较好。用模板字符串层层嵌套,连在一起之后使代码变得很难读。而且编辑器对于模板字符串里面代码的着色也很差。 148 | 149 | ps2:箭头函数也建议只对简单函数使用。如果要处理动态this和使用arguments的话,要使用传统函数。 150 | 151 | ## 5.0.3 152 | 153 | 在4.5.5版本里,原本下载链接没加target="_blank",下载时却会打开新页面,后来加上之后反倒不打开了。然而现在chrome更新到65之后,加了target="_blank"的开始出现新页面了,我只好再去掉。很奇怪。 154 | 155 | ## 5.0.6 156 | 157 | - tag搜索页下载时按照收藏数从高到低下载。 158 | 159 | tag搜索页有时图片太多,比如筛选某个tag,条件是最低收藏数3000,有两千来张。下载花了很久,下载的时候我就想,早知道就只下载4000以上的了,低于4000的就不要了。但是由于之前的下载顺序是从低到高,3000 → 4000 → 5000…… 后悔的时候已经晚了。 160 | 161 | 现在改成了从高到低下载,10000 → 9000 → 8000…… 这样,当你感觉“到这里已经够了”的时候,就可以立即停止下载了。那些收藏数低的不想要就不要了。 162 | 163 | ## 5.1.0 164 | 165 | 2018/4/12,最近有不少人遇到有漏下的情况,但是以前一直没这个问题。而且tampermonkey里确实是每个图片都下载到了,下载请求也发送到chrome了,但是漏下的这些任务失败了,并且没有显示在Chrome的下载列表里。最可能的原因是在短时间内点击了多次下载按钮,导致发送了多次下载请求。但是以前一直没问题,推测可能是chrome新版有什么改动导致的问题。 166 | 167 | 目前有两个思路解决这个漏下的问题,方法1是把并发下载线程 download_thread_deauflt 改成1,单线程下载,不会漏下。方法2是保证每两次点击下载按钮之间有足够的时间间隔,这样既可以多线程下载,也不会漏下。目前采用第二种方法。 168 | 169 | ## 5.2.0 170 | 171 | 1.任务流程改为在title上提醒,不再使用弹窗。(但可设置use_alert参数继续使用弹窗) 172 | 173 | 提示字符的含义: 174 | 175 | ``` 176 | 0 复原 177 | ↑ 抓取中 178 | → 等待下一步操作(tag搜索页) 179 | ▶ 准备下载 180 | ↓ 下载中 181 | ║ 下载暂停 182 | ■ 下载停止 183 | √ 下载完毕 184 | ``` 185 | 186 | 2.可以保存用户的命名规则。 187 | 188 | 3.修复pixivision上cosplay图片的下载 189 | 190 | 4.GM_xmlhttpRequest可以把responseType设置为blob了,不用再手动转换为blob了。这应该会提升运行效率…… 191 | 192 | 另外,极少数情况下,下载面板上的总数量会漏掉一个作品的图片数量,导致已下载数量超过总数量,如295/265。这里只是显示问题,以已下载数量为准。目前对此问题还没有什么头绪。 193 | 194 | ## 5.3.0 195 | 196 | 2018年4月份开始,p站陆续对作品页进行改版。不仅页面结构全变了,而且作品也内也不使用jQuery了。 197 | 198 | 此版本先修复在作品页外下载的问题。 199 | 200 | 在作品页内下载还不行,先在 _无权访问1 里添加提示。下个版本再修改。 201 | 202 | 另外,新版直接显示收藏数了,等以后统一是新版了,可以更新到命名规则里。 203 | 204 | 后续还要添加下载相关作品的功能。 205 | 206 | ## 5.4.0 207 | 208 | 更改了获取语言设置的方法。 209 | 210 | 在作品引入了jQuery,并修复了作品页的下载功能。 211 | 212 | 在作品页修改了css样式,以保持统一。 213 | 214 | ## 5.5.0 215 | 216 | **新增功能:** 217 | 218 | - 支持下载相关作品(作品页下方的相关作品) 219 | 220 | 相关作品里出现的作品其实和添加收藏后的相似作品是一致的。但是相关作品有个自己的api,如: 221 | 222 | https://www.pixiv.net/ajax/illust/68375792/recommend/init?limit=180 223 | 224 | 这个api最大可以返回180个作品,但相似作品的上限要大得多。所以下载相关作品时,借用相似作品的下载流程。 225 | 226 | **bug修复:** 227 | 228 | - p站改版后,作品页面切换作品不刷新了。这可能会导致下载到的始终是第一页,对此问题进行了修复。 229 | 230 | - 解决漏下illustType为1的作品的bug。 231 | 232 | **优化修改:** 233 | 234 | - 使用了新版作品页用于获取作品信息的api,如: 235 | 236 | https://www.pixiv.net/ajax/illust/67050051 237 | 238 | 注意最后不能带斜杠。这个api老版也能用,所以 getIllustPage() 里不需要区分新旧版了,直接都改成用新版的。 239 | 240 | *但新的api有个问题,就是可能无法获取到作者名字。userName只能从tag信息里获取,如果一个作品没有tag,那就获取不到作者名字了。发生这种情况时,把作者名字留空。* 241 | 242 | - 从新的api里可以直接获取多p作品的原图url,并且后缀名是正确的。这样就省下了一次页面抓取,加快了多p作品的抓取速度。 243 | 244 | - 优化了命名规则。 245 | 246 | - 修改了处理404的代码。之前获取作品页的时候获取的是html页面,404了也可以进入success处理。现在改为获取json数据了,404不进入success了,要在外面statusCode里处理。 247 | 248 | ## 5.6.0 249 | 250 | **新增功能:** 251 | 252 | - 在 showcase 特辑里面也可以使用全部的命名方式了。 253 | 254 | - 命名规则里都可以使用{bmk}了。(之前只有在tag搜索页可以用) 255 | 256 | - 添加了筛选收藏数的按钮。(大于等于指定收藏数的作品才会被下载) 257 | 258 | **其他** 259 | 260 | - 获取动图信息有新的api,在作品信息api后面加上/ugoira_meta,如: 261 | 262 | https://www.pixiv.net/ajax/illust/68437318/ugoira_meta 263 | 264 | 这里面包含原文件(zip)的url和帧率信息。 265 | 266 | - pixivision 预计以后不再维护。 267 | 268 | 首先它和pixiv主站是跨域的,使得同步下载流程比较麻烦。(比如我计划在 pixivision 里也去获取作品信息api,这样在 pixivision 里下载时,可以使用更多的命名规则了。但是jQuery的ajax无法设置跨域,用GM_xmlhttpRequest的话改动成本又太高)。 269 | 270 | 其次pixivision上面的很多板块都已经停止更新了,插画没有停止更新,但是插画是和 showcase 特辑同步的,所以从 showcase 特辑下载就行了。 271 | 272 | ## 5.6.1 273 | 274 | 原本tag搜索页的快速搜索功能, 最大只到10000users入り。但是这个tag从其本意来讲,是10000-20000,这样,更高收藏数的作品就筛选不出来了。所以现在增加了20000/30000/50000的选项。 275 | 276 | ## 5.6.2 277 | 278 | tag搜索页和大家关注的新作品都有一次改版,改版前是源码里包含着列表的DOM元素,改版后是把作品信息改成json方式保存到源码里了。因为p站的改版一直是新旧版共存过渡,所以当时有个tag_search_is_new参数来区别新旧版。但是到现在应该所有人都改成新版了。tag搜索页可以把tag_search_is_new去掉,但是page_type === 10里面还要留着。因为10里面的大家的新作品是旧版,关注的人的新作品是新版,这俩还得区分。现在先把tag搜索页的旧代码去掉了,并把tag_search_is_new改成list_is_new。 279 | 280 | ## 5.6.4 281 | 282 | p站自己用的jQuery地址为: 283 | https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js 284 | 285 | 之前我担心有些人用改dns的方法上p站的话,可能打不开google的网址,所以用了下面的网址: 286 | https://code.jquery.com/jquery-2.0.3.min.js 287 | 288 | 但是有人打不开这个。怀疑是少数。如果人再有人打不开jquery官网的这个,就改成p站自己的网址吧。 289 | 290 | ## 5.6.6 291 | 292 | 前些版本我更改了命名规则,现在有人想用原来的格式,增加了 use_original_name 参数来控制该选项。 293 | 294 | ## 5.6.7 295 | 296 | 屏蔽了新版的一些广告 297 | 298 | ## 5.6.8 299 | 300 | ### 添加一键收藏功能,并且附带tag。(只在新版有用) 301 | 302 | 但是此功能目前有个小瑕疵,如果点了快速收藏,之后向前/后切换一张作品,再切换回来,回来之后会看到又变成没有收藏时的状态了。这是因为页面没有刷新,不要介意。只要快速收藏时显示了收藏成功就没问题。 303 | 304 | 同时还有其他问题要注意: 305 | 306 | - 免费用户每个作品只能添加 10 个 tag,如果作品的 tag 数量超过10个,那么多出来的就不会被保存。 307 | 308 | - 收藏时添加的 tag 貌似有 20 个字符的最大长度限制,如添加“バーチャルYouTuber5000users入り”会被截断成为“バーチャルYouTuber5000use”,即使是手动添加也会被截断。 309 | 310 | #### 一键收藏功能 API: 311 | 312 | ```https://www.pixiv.net/rpc/index.php``` 313 | 314 | 以 post 方式发送一些参数(并且需要发送 cookie),示例: 315 | 316 | ``` 317 | mode: save_illust_bookmark 318 | illust_id: 68201395 319 | restrict: 0 320 | comment: 321 | tags: Fate/GrandOrder セイバー・ブライド 322 | tt: 489520361bf22a5bb897306b3d9cdc1b 323 | ``` 324 | 325 | 参数说明: 326 | 327 | ``` 328 | mode: save_illust_bookmark 此项固定 329 | 330 | illust_id: 68201395 id 按需要修改 331 | 332 | restrict: 0 此项固定 333 | 334 | comment: 保持留空即可 335 | 336 | tag:格式为 encodeURI 编码后的字符,如果要添加多个tag,不同tag之间用空格分开(%20)。 337 | 338 | tt:可以从 pixiv 页面上的全局变量获取:globalInitData.token 339 | ``` 340 | 341 | 另外,删除收藏用的不是这个 api,而且使用的 id 也不是作品 id,而是该书签的 bookmark_id。 342 | 343 | ## 5.7.0 344 | 345 | ### 增加看图模式(只在新版、多 p 作品页有用) 346 | 347 | 有普通看图和全屏看图模式。[查看效果(新浪微博](https://weibo.com/1678634987/GmpQnpafZ) 348 | 349 | - 使用了 [Viewer.js](https://github.com/fengyuanchen/viewerjs) 库,感谢原作者~ 350 | 351 | Viewer.js 本来需要引入两个文件,js 文件和 css 文件,为了方便调用,我将两个文件混合后上传到了 greasyfork 上。url 为: 352 | 353 | ``` 354 | https://greasyfork.org/scripts/369647-viewer-js-mix/code/Viewerjs%20mix.js 355 | ``` 356 | 357 | - 注意: 358 | 359 | 有些时候 greasyfork.org 也会被墙,如果打不开上面的 js,那么自然也就无法使用看图模式了。 360 | 361 | - 优化了 Viewer.js 的看图体验。 362 | 363 | 比如要看图片的100%比例大小的时候,原本一直有查看器的元素挡在图片上,看着不舒服。播放幻灯片的话可以进入全屏模式,会隐藏这些元素,但是图片比例不是100%了。现在我结合了一下,点击 1:1 按钮时会进入全屏状态查看,比例是100%。(必须要点击这个按钮,因为进入全屏需要用户手动操作触发) 364 | 365 | 原本的全屏状态里(播放幻灯片时),用户不能切换图片,现在全屏状态下也可以切换图片了,并且图片都是保持100%比例打开的。但是有个瑕疵,可能因为 Viewer.js 本来没有设计这个功能,导致图片放大时位置会变化,看上去产生了抖动。 366 | 367 | - 注意: 368 | 369 | 不要用左右方向键 ← → 来切换图片,因为这样会导致 pixiv 也响应了左右方向键,从而切换了作品。还是用鼠标来切换图片吧。 370 | 371 | 你在p站切换作品时,推荐使用左右方向键 ← →。如果用浏览器的前进后退按钮来操作,那么切换到的这个页面不会触发快速收藏和看图模式。 372 | 373 | - pixiv 上缩略图的 url 开头是这样的, ```https://i.pximg.net/c/240x240/img-master/img/```,例如: 374 | 375 | ``` 376 | https://i.pximg.net/c/240x240/img-master/img/2018/06/17/00/10/40/69264102_p4_master1200.jpg 377 | ``` 378 | 379 | 这样加载就会很快了,如果加载大图的话,速度就太慢了。 380 | 381 | 缩略图始终都是 jpg 格式,原图则有 jpg、png 两种格式。(还会有 zip 的) 382 | 383 | ## 5.7.1 384 | 385 | 优化了看图体验。 386 | 387 | 原本在全屏模式(100%比例)中看图时,如果图片是之前尚未加载的图片,那么加载后显示的比例不是100%。现在手动给它设置一次宽高,成为100%。 388 | 389 | ### pixiv网址的缩写: 390 | 391 | 最近发现画师页面和作品页面的网址都可以使用缩写,如: 392 | 393 | ``` 394 | https://www.pixiv.net/member.php?id=212801 395 | 缩写为: 396 | https://www.pixiv.net/u/212801 397 | 398 | https://www.pixiv.net/member_illust.php?mode=medium&illust_id=66509867 399 | 缩写为: 400 | https://www.pixiv.net/i/66509867 401 | ``` 402 | 403 | ## 5.7.2 404 | 405 | - 可以在下载前预览图片的名字; 406 | 407 | - 恢复了单图原来的命名规则,即加上 _p0。 408 | 409 | 预览图片名的结果如下: 410 | 411 | ``` 412 | 69052408_p0.png: bmk_8262-69052408_p0-tags_電撃文庫,ガーリー・エアフォース,おへそ,グリペン,ピンク髪ロング,5000users入り.png 413 | ``` 414 | 415 | 每个名字前面加了这个图片默认的名字,如 69052408_p0.png。默认名字和实际名字中间用 ```: ``` 分割。 416 | 417 | 这样,如果用户使用迅雷、IDM 之类软件下载图片,下载后的图片只有默认名字,再拷贝本工具的命名,就可以编写脚本,把图片的默认名字修改为本工具的名字。 418 | 419 | 以 cmd 为例,可以把上面的名字修改为 cmd 命令来执行: 420 | 421 | ``` 422 | ren 69052408_p0.png "bmk_8262-69052408_p0-tags_電撃文庫,ガーリー・エアフォース,おへそ,グリペン,ピンク髪ロング,5000users入り.png" 423 | ``` 424 | 425 | 借助文本编辑器,用户可以批量的把本工具生成的图片名修改为 shell 命令。 426 | 427 | ## 5.7.7 428 | 429 | p 站自己的收藏按钮添加了快速收藏功能,但是不带 tag,和我自己按钮的快速收藏功能冲突,现在我把原本的收藏按钮隐藏了,全部使用脚本的快速收藏。 430 | 431 | 另外根据 [thelastfantasy 的建议](https://github.com/xuejianxianzun/XZPixivDownloader/issues/4),把动图从 zip 后缀名改为了 ugoira 后缀名,请用 HoneyView 打开查看。 432 | 433 | ## 5.8.0 434 | 435 | - pixiv 的改版 436 | 437 | p 站在完成了作品页的改版后,又要进行新改版: [pixiv的个人资料页面将全新改版](https://www.pixiv.net/info.php?id=4704)。 438 | 439 | 受此影响的页面有: 440 | 441 | 画师(或自己)的主页、插画分类列表、漫画分类列表、收藏页面,以及上述页面里的 tag 列表页。 442 | 443 | 旧版的个人主页里有“动图”作品的列表页(第一行),新版里面已经没有这个分类了,这个 url 会跳转到**插画**作品列表页: 444 | 445 | ```https://www.pixiv.net/member_illust.php?id=4693961&type=ugoira``` 446 | 447 | ```https://www.pixiv.net/member_illust.php?id=4693961&type=illust``` 448 | 449 | pixiv 的新版都不再使用 jQuery 了。 450 | 451 | 从个人资料页面进入插画页,是无刷新的(pushState),无刷新的地方越来越多了,体验好一些,不过下载工具需要修改更多地方。 452 | 453 | - 本工具的修改 454 | 455 | 之前的 page_type: 456 | 457 | 2: 画师列表页(插画、漫画) 458 | 459 | 3:画师的 tag 列表页 和 收藏的 tag 列表页; 460 | 461 | 4:收藏页面。 462 | 463 | 新版里这 3 种都改了。而且使用的无刷新加载技术,需要动态监控 url,对应改变 page_type。 464 | 465 | 现在 page_type 2/3/4 全部整合到了 2 里。 466 | 467 | 本工具以新版为准,旧版功能可以用新版实现的,就按新版处理。 468 | 469 | - 其他修改: 470 | 471 | 1. 本来,进入自己的收藏页面时,没带自己的 id(第一行): 472 | 473 | ``` 474 | https://www.pixiv.net/bookmark.php 475 | https://www.pixiv.net/bookmark.php?id=9460149 476 | ``` 477 | 478 | 不带 id 的话,还是旧版的界面,带了 id 才是新版的。所以这里添加了个修改,如果不带 id 自动跳转到带 id 的。 479 | 480 | 2. 无刷新加载对 page_type 1 和 2 的影响 481 | 482 | 从新版个人资料页可以无刷新进入作品页,这种情况下,作品页也可以通过浏览器的后退功能,无刷新返回个人资料页。这就造成了两种页面类型可以无刷新切换。(不过必须是先打开 2,然后进入1, 1才能通过返回按钮来无刷新回到 2。如果一开始打开的是 1,那么 1 无法不刷新进入 2) 483 | 484 | 为了能让脚本适根据 page_type 动态切换,对代码做了不少修改。 485 | 486 | 需要记住的是,无刷新切换时,两种类型共用一个页面,所以绑定全局事件时需要注意这一点,避免冲突或者重复绑定。 487 | 488 | - 新版使用的 api 分析: 489 | 490 | [画师主页](https://www.pixiv.net/member.php?id=27517): 491 | 492 | **1** ```https://www.pixiv.net/ajax/user/27517/profile/all``` 493 | 494 | 这个 api 包含了该画师所有作品的 id。包含插画和漫画,但分别只有最近的 12 个作品有详细信息。因为个人主页只展示12个插画和12个漫画。 495 | 496 | 先在这里获取所有作品 id ,之后再获取作品详细信息。 497 | 498 | [画师的所有作品列表页](https://www.pixiv.net/member_illust.php?id=27517) ,是把插画和漫画合在一起的列表页。api 不用变。 499 | 500 | [画师的插画列表页](https://www.pixiv.net/member_illust.php?id=27517&type=illust):(可以跟很多 ids) 501 | 502 | ```https://www.pixiv.net/ajax/user/27517/illusts?ids%5B0%5D=66979373``` 503 | 504 | 这是 pixiv 加载插画列表里的作品用的,包含有作品详细信息,但不全面,比如没有画师名和收藏数。所以不使用这个 api,先用上面的 **1** api 获取 id 列表,最后获取作品详细信息。 505 | 506 | [画师的漫画列表页](https://www.pixiv.net/member_illust.php?id=27517&type=manga):(可以跟很多 ids) 507 | 508 | ```https://www.pixiv.net/ajax/tags/frequent/illust?ids%5B0%5D=20830181``` 509 | 510 | 不使用这个 api,理由同上。 511 | 512 | [画师的插画 tag 列表页](https://www.pixiv.net/member_illust.php?id=27517&type=illust&tag=%E5%A5%B3%E3%81%AE%E5%AD%90): 513 | 514 | ```https://www.pixiv.net/ajax/user/27517/illusts/tag/%E5%A5%B3%E3%81%AE%E5%AD%90?offset=0&limit=24``` 515 | 516 | 把 limit 设置为 999999 来获取所有列表,然后取出 id 列表,最后获取作品详细信息。 517 | 518 | [画师的漫画 tag 列表页](https://www.pixiv.net/member_illust.php?id=27517&type=manga&tag=%E5%A5%B3%E3%81%AE%E5%AD%90):(和插画 tag 的区别在于中间字段不同) 519 | 520 | ```https://www.pixiv.net/ajax/user/27517/manga/tag/%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB?offset=0&limit=24``` 521 | 522 | [画师的漫画和插画 tag 列表页](https://www.pixiv.net/member_illust.php?id=27517&tag=%E5%A5%B3%E3%81%AE%E5%AD%90) 523 | 524 | 处理同上。 525 | 526 | [书签主页](https://www.pixiv.net/bookmark.php?id=9460149): 527 | 528 | ```https://www.pixiv.net/ajax/user/9460149/illusts/bookmarks?tag=&offset=0&limit=24&rest=show``` 529 | 530 | [书签的 tag 列表页](https://www.pixiv.net/bookmark.php?id=9460149&tag=C94&rest=show):(和主页的区别是带了 tag) 531 | 532 | ```https://www.pixiv.net/ajax/user/9460149/illusts/bookmarks?tag=R-18&offset=0&limit=24&rest=show``` 533 | 534 | - api 总结 535 | 536 | 1. 获取画师所有作品列表: 537 | 538 | ```https://www.pixiv.net/ajax/user/27517/profile/all``` 539 | 540 | 2. 获取画师某个 tag 的作品列表:(区分 illusts 和 manga) 541 | 542 | ```https://www.pixiv.net/ajax/user/27517/illusts/tag/%E5%A5%B3%E3%81%AE%E5%AD%90?offset=0&limit=24``` 543 | ```https://www.pixiv.net/ajax/user/27517/manga/tag/%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB?offset=0&limit=24``` 544 | 545 | 3. 获取书签或书签的 tag 列表:(区别带不带 tag) 546 | 547 | ```https://www.pixiv.net/ajax/user/9460149/illusts/bookmarks?tag=&offset=0&limit=24&rest=show``` 548 | ```https://www.pixiv.net/ajax/user/9460149/illusts/bookmarks?tag=R-18&offset=0&limit=24&rest=show``` 549 | 550 | ## 5.8.3 551 | 552 | p 站书签页,获取收藏数据的 api 改了,limit 每次只能获取100,不能99999了。不知道以后其他能 99999 的会不会也改成100,好烦啊。 553 | 554 | ## 5.9.0 555 | 556 | - 可以将动图转换为 gif 557 | 558 | 获取动图信息的 API 如: 559 | 560 | ```https://www.pixiv.net/ajax/illust/69979772/ugoira_meta``` 561 | 562 | 包含原文件(zip)的url和帧率信息。 563 | 564 | 静态图片网址可以从源文件网址替换得出。源文件网址如: 565 | 566 | ```https://i.pximg.net/img-zip-ugoira/img/2018/08/02/14/08/01/69979772_ugoira1920x1080.zip``` 567 | 568 | 压缩包里的静态图片网址如: 569 | 570 | ```https://i.pximg.net/img-original/img/2018/08/02/14/08/01/69979772_ugoira0.jpg``` 571 | 572 | 最后的序号从 0 开始,依次增加。 573 | 574 | 我本来想直接用静态图片来生成 gif,但是在转换成 gif 时会遇到跨域问题。最后还是只能先加载 zip 文件,再从 zip 文件里提取静态图片。 575 | 576 | - 使用的库: 577 | 578 | [zip.js](https://github.com/gildas-lormeau/zip.js) 579 | 580 | [gif.js](https://github.com/jnordberg/gif.js) 581 | 582 | 用户脚本使用库太麻烦了,只能引用外部网址的库,不能像浏览器扩展那样,把库包含到自己的文件夹。 583 | 584 | ps:当我把更改同步到 Chrome 扩展时,才发现扩展也有不方便的地方,那就是 worker 的 url。如果依旧从远程地址引入倒还行,但要引入扩展文件夹内的 js 作为 worker,没有很好的办法,只能通过获取它的文本来创建 blob url。所以现在简单粗暴的全塞到 content.js 里了。 585 | 586 | ## 5.9.1 587 | 588 | p站作品页面一些结构变了,导致多图作品的缩略图列表位置变得靠下了,现在修复。 589 | 590 | ## 5.9.2 591 | 592 | 有人反应动图分类列表页,下载到的是全部作品,而不是动图作品。如: 593 | 594 | ```https://www.pixiv.net/member_illust.php?id=573302&type=ugoira``` 595 | 596 | 因为在新版里没有“动图”作品列表了,动图合并到了“插画”列表里,上面的网址会被导航到“插画”列表里。 597 | 598 | ```https://www.pixiv.net/member_illust.php?id=573302&type=illust``` 599 | 600 | 因为没有(或者没有找到)单独获取动图的 api,所以用了另一个办法,检测到是动图分类时,直接设置为排除单图、多图,只下载动图。 601 | 602 | ## 5.9.6 603 | 604 | 点击收藏按钮时,会自动点赞。 605 | 606 | ## 5.9.7 607 | 608 | 新版列表页改成一页 48 个了,同步修改。 609 | 610 | ## 5.9.9 611 | 612 | 在画师的列表页里下载时,把 url 倒序排列,这样是为了先下载最新作品,后下载早期作品。 613 | 614 | ## 6.0.0 615 | 616 | 界面优化 617 | 618 | 增加和修改一些设置项 619 | 620 | 改进暂停、停止功能 621 | 622 | ## 6.0.1 623 | 624 | 修复 bug 和文本错误 625 | 626 | 修改 tag 搜索页第一个按钮的颜色 627 | 628 | ## 6.0.2 629 | 630 | 记忆一些设置: 631 | 632 | - 多图作品设置 633 | - 设置作品类型 634 | - 必须含有 tag 635 | - 不能含有 tag 636 | - 是否显示封面 637 | - 是否快速下载 638 | - 设置下载线程 639 | - 设置命名规则 640 | 641 | ## 6.0.5 642 | 643 | 添加了一个设置项: 644 | 645 | - 添加标记名称 646 | 647 | ## 6.1.0 648 | 649 | - 优化了界面 650 | - 把排除类型里的“收藏作品”改为一个单独的选项,含义更加准确。 651 | - 修复bug 652 | 653 | ## 6.1.1 654 | 655 | 修复了火狐上,不会出现 tip 提示框的 bug。 656 | 657 | ## 6.1.3 658 | 659 | 默认隐藏下载区域,在可以进行下载时才显示。 660 | 661 | ## 6.1.5 662 | 663 | 修改出了 bug,改回去。 664 | 665 | ## 6.1.6 666 | 667 | 网友 [道滿](https://zhtw.me/) 翻译了繁體中文 668 | 669 | ## 6.2.0 670 | 671 | 可以设置文件夹名称 672 | 673 | 重复文件只能加序号,不能直接覆盖。Chrome 扩展版可以直接覆盖。 674 | 675 | 在右侧添加快速下载按钮 676 | 677 | 快速下载不建立文件夹 678 | 679 | 添加了设置文件夹的教程 680 | 681 | 添加标记更快捷 682 | 683 | ## 6.2.4 684 | 685 | Firefox 上我搞不出来怎么建立文件夹了,先在 Firefox 上把这个功能屏蔽吧。 686 | 687 | 还是 chrome 好。 688 | 689 | ### 其他 690 | 691 | 最近我发现相关作品很不“相关”,api 似乎没改,但是出来的结果和以前相比,相关度很差,基本不怎么相关。 692 | 693 | 对比一下: 694 | 695 | https://www.pixiv.net/member_illust.php?mode=medium&illust_id=71395570 696 | 697 | 底部的相关作品 698 | 699 | https://www.pixiv.net/bookmark_detail.php?illust_id=71395570 700 | 701 | 底部的相似作品 702 | 703 | 以前这两部分出来的作品是一致的,但最近“相关作品”变得不怎么相关了。 704 | 705 | ## 6.2.7 706 | 707 | 以前从画师列表页进入作品页无刷新,从作品页进入画师列表页是要刷新的。现在不一样了,点击作品页的用户名,可以无刷新进入列表页。所以在作品页内也要监听 history 的变化了。 708 | 709 | 另外作品页内的画师名的 class 最近变了两次,考虑找个别的办法来获取画师名。 710 | 711 | ## 6.2.8 712 | 713 | 从 title 获取画师名。 714 | 715 | ## 6.2.9 716 | 717 | 添加了 Firefox 扩展的提示。 718 | 719 | ## 6.3.1 720 | 721 | 列表页有 1 个「,包裹用户名。内容页有 2 个「,第一个包裹作品名,第二个包裹用户名。但有些用户名里就有「,导致列表页被识别成了内容页,所以增加了判断条件。 722 | 723 | https://www.pixiv.net/member.php?id=2793583 724 | 725 | 但在这种情况下,获取的画师名不包含它本身带的“」”符号,是不完整的。 726 | 727 | ## 6.4.0 728 | 729 | - 删除了 showcase 的相关代码 730 | 731 | pixiv 彻底取消了 showcase 页面,直接跳转到 pixivision 了。 [查看公告](https://www.pixiv.help/hc/zh-tw/articles/360000226574) 732 | 733 | - 删除了 响应关联作品 的相关代码 734 | 735 | 怀疑 pixiv 已经取消了以往的“响应关联作品”的功能。以前的响应网址打开没有内容了。 736 | 737 | - 修复反复跳转后图片缩略图失效的问题 738 | 739 | - 优化获取用户 id 740 | 741 | 获取用户 id 从查找头像元素改成了从 html 源码匹配。这样应该不会那么频繁的修改了。 742 | 743 | - 适应改版 744 | 745 | 画师的插画和漫画分类列表页,url 多了一种新情况,适配之。 746 | 747 | 另外 p 站最近改版也修改了许多 classname 748 | 749 | - 优化代码。 750 | 751 | ----------- 752 | 753 | ### 优化代码内容: 754 | 755 | - 解除对 jQuery 的依赖。 756 | 757 | - 一些 for 循环改成 forEach()、map()、reduce()、for of。 758 | 759 | - 一些 for in 遍历对象,改成 for of 遍历 Object.keys()、Object.values()。 760 | 761 | - 把 indexOf 改为 includes。 762 | 763 | - 函数参数 rest。 764 | 765 | - 解构赋值 766 | 767 | - 部分 if 改成 switch。 768 | 769 | - 优化 addCenterButton 函数,添加按钮时减少了重复代码。 770 | 771 | - 去掉一些用作匿名函数的 { } 代码块标记。 772 | 773 | - 一些绑定事件时的匿名函数改成了箭头函数。 774 | 775 | - 一些 innerHTML 改成了 textContent。 776 | 777 | - 删除作品的标记从 DOM 标签上的属性改成了一个变量。 778 | 779 | - 所有 css 统一添加到同一个样式表里。 780 | 781 | - 优化操作 outputInfo 的代码 782 | 783 | - 精简手动删除作品的代码,并提升性能 784 | 785 | - 优化了看图器的一些代码。 786 | 787 | (发现 Chrome 71 已经支持 fullscreenchange 这个全屏 API 了,不能加前缀了) 788 | 789 | - 匹配字符串的正则方法从 match 改成 exec,使用分组 790 | 791 | - fetch 代码优化 792 | 793 | - 其他改进。 794 | 795 | ## 6.4.1 796 | 797 | 用网页标题做文件夹名时,会去掉最前面的消息数。 798 | 799 | ## 6.4.2 800 | 801 | 优化了加载 gif 所用的 js 文件的代码。代码更简洁,逻辑更清晰。 802 | 803 | ## 6.4.3 804 | 805 | 略微精简代码,适配快速收藏改版。 806 | 807 | ## 6.4.4 808 | 809 | 快速收藏部分,因为 p 站改版 class 经常变,所以从父元素查找,父元素的 class 变化没那么频繁。 810 | 811 | ## 6.4.5 812 | 813 | - 增加“设置宽高比例”,当设置为下载横图或竖图时,不下载方图。 814 | 815 | 这个 [含有方图的网址](https://www.pixiv.net/member_illust.php?id=10309098&tag=%E6%B5%9C%E9%A2%A8) 有 1 个方图, id = 61632819 816 | 817 | - 在 tag 搜索页,使一些设置立即生效(以前有些设置要等到下载时才生效) 818 | 819 | - 优化代码,优化任务流程,提高效率 820 | 821 | ## 6.4.6 822 | 823 | 修复tag搜索页图片下载两遍的问题 824 | 825 | ## 6.5.0 826 | 827 | 文件夹、文件名设置里可以自由建立多级文件夹了。 828 | 829 | 安全的文件名的正则里添加了一种情况,去掉末尾的点“.”。在 Windows 上末尾的点会消失,导致建立文件夹失败,如有个画师名字“ち.”。 830 | 831 | ## 6.5.1 832 | 833 | - 修复暂停后继续下载会有部分图片重复下载的 bug: 834 | 835 | 以前把 tag 搜索页设置为按收藏数从高到低下载,但当时是反转数组,操作不对,而且导致暂停后再继续下载,会下载到几张重复图片,漏掉相同数量的正常图片。现在修复了。 836 | 837 | 在 tag 搜索页之外,理论上应该是没有这个 bug 的,毕竟流程不一样。但我测试的时候偶然在画师列表页也遇到了这个情况。然而之后多次测试无法复现,暂且不管了。 838 | 839 | - 优化部分文本。 840 | 841 | - 更新了截图 842 | 843 | ## 6.5.2 844 | 845 | 有些作品如 565435,API 返回的数据里有 tag 却不包含画师名,很奇怪,对这种情况做了修复。 846 | 847 | ## 6.5.3 848 | 849 | - 看图模式时预加载下一张图片 850 | 851 | - 优化部分文本。 852 | 853 | ## 6.5.4 854 | 855 | 使脚本版和扩展版同时只运行一个。 856 | 857 | 视情况不同,两个版本哪个先运行是不固定的,所以两个版本里都做了检测。 858 | 859 | ## 6.5.5 860 | 861 | 增加了扩展版图标的动画效果,提示用户去安装浏览器扩展版。原因如下。 862 | 863 | **Chrome 72 的问题** 864 | 865 | Chrome 72 因为增加了一些限制,导致 Tampermonkey 一些功能失效,导致本工具下载出现异常。 866 | 867 | **解决办法:** 868 | 869 | - 升级 Tampermonkey 到最新版本(在 Chrome 上,需要 Tampermonkey 4.8 或更高版本) 870 | 871 | - 此外,你也可以切换到本工具的浏览器扩展版,扩展版没有出现这个问题。 872 | 873 | ## 6.5.6 874 | 875 | 因为有些人没注意到右上角推荐 chrome 的图标,所以这次我加了颜色,闪动频率更快,希望可以挽救星际用户。 876 | 877 | ## 6.5.7 878 | 879 | 检测脚本版因 Chrome 72 导致不能正常下载的情况,加一个弹窗提醒。只弹出一次。 880 | 881 | ## 6.6.0 882 | 883 | 同步扩展版的修改. 合并命名规则输入框,修复快速收藏失效等. 884 | 885 | ## 6.6.1 886 | 887 | 根据投票结果, 保留了命名规则里的空标记. 空标记会原样添加到文件(夹)名里. 888 | 889 | 之前从扩展版同步修改,导致去掉了"如何使用"文件夹的按钮,恢复之. 并添加文字提示"要在 Firefox 上建立文件夹,请使用扩展版。" 890 | 891 | 现在 Firefox 的 TM 依旧不能建立文件夹. 892 | 893 | ## 6.6.2 894 | 895 | 添加命名规则的示例。 896 | 897 | ## 6.6.3 898 | 899 | 修复动图额外建立了文件夹的问题。 900 | 901 | ## 6.6.4 902 | 903 | 修改命名规则后,快速下载也会建立文件夹了。现在修改成不建立文件夹的状态。 904 | 905 | ## 6.6.5 906 | 907 | 文件名标记里有些值是数字(如 bmk),导致 replace 报错 `once.replace(safe_fileName_rule, '_')`。现在统一转换为字符串,避免错误。 908 | 909 | ## 6.6.6 910 | 911 | - 在 sortByProperty 里把参数都转换成了数字。 912 | 913 | 之前传入的参数是字符串,按首位比较的,不准确。转换成数字以保证结果准确。 914 | 915 | - 暂停和继续下载添加定时器。 916 | 917 | 如果点了暂停,然后点开始继续,中间间隔时间很短,可能会出问题。所以加上了延时。 918 | 919 | ## 6.6.7 920 | 921 | - 修改了右侧按钮样式使其更加明显 922 | 923 | - 添加了建立文件夹的提示 924 | 925 | - 优化日文文本 926 | 927 | - 修复 getUserName 的 bug 928 | 929 | 之前 getUserName 会使用 old_title,这是有问题的,不同语言的 title 不一样,导致严重错误,英语语言下完全无法下载。现在修复了。 930 | 931 | ## 6.6.8 932 | 933 | 修复 bug 934 | 935 | ## 6.6.9 936 | 937 | p 站最近在 tag 搜索页的 R-18 分类里,增加了广告信息,导致抓取出错,现在修复这个问题。 938 | 939 | ## 6.7.0 940 | 941 | - 增加了 id_num 命名字段 942 | 943 | - 停止下载时添加时间间隔。 944 | 945 | ## 6.7.1 946 | 947 | - css 优化 948 | 949 | - 查看多 p 图片的页面 [示例](https://www.pixiv.net/member_illust.php?mode=manga&illust_id=67618513) 并不能进行下载,但之前显示了下载图标,现在去掉 950 | 951 | ## 6.7.2 952 | 953 | - 修复 getUserName 的 bug 954 | 955 | 之前从 dom 里获取,但是这样 p 站一改版就出问题,所以还是从 api 获取比较好。所以添加了 getIllustInfo 函数。虽然可能会多次调用它,但是有缓存,所以问题不大。 956 | 957 | ## 6.7.3 958 | 959 | - css 优化 960 | 961 | - 其实主要原因是 Firefox 扩展被下架了,补充了一些隐私政策等信息,提交新版本进行审核。 962 | 963 | - 更新了 readme 里的捐赠信息,之前放的博客链接,但是需要翻墙才能打开。所以现在直接放图片了。 964 | 965 | ## 6.7.4 966 | 967 | - 添加了 {p_num} 标记,也就是图片的 p 数。 968 | 969 | - 因为格式化程序的改变,函数名和括号之间增加了空格。参数列表的逗号后面也加了空格。 970 | 971 | ## 6.7.5 972 | 973 | 画师作品列表页带 tag 时的 api 发生了变化,修改之。 974 | 975 | ## 6.7.6 976 | 977 | - 对合法的文件名的规则进行修改 978 | 979 | 现在的 Chrome 下载扩展 API 不允许文件名里含有 `~` 了,所以增加了对此情况的处理。 980 | 981 | 另外增加的 `\u220b\` 是一个特殊字符,有时候会遇到,它没有宽度。它会导致 chrome 下载文件时报错,文件名不合法。 982 | 983 | ## 6.7.7 984 | 985 | - 优化繁体中文文本 986 | 987 | - 修复快速收藏功能,感谢 yuzhan1990。 988 | 989 | ## 6.7.8 990 | 991 | 快速下载时,如果只有一个文件,则不建立文件夹。如果大于一个图片,则建立文件夹。 992 | 993 | ## 6.8.0 994 | 995 | 在书签页面,可以给“未分类”的书签批量加上 tag。这样可以节省大量的时间。 996 | 997 | ## 6.8.1 998 | 999 | 优化体验。之前在一些非书签页也会显示添加 tag 按钮,现在限制在只在书签页显示。但目前有个问题,在别人的书签页里也会显示。 1000 | 1001 | ## 6.8.2 1002 | 1003 | 优化了获取 token 的方式,添加 tag 的按钮可以在书签页直接出现了。之前需要先用一次快速收藏才会出现这个按钮。 1004 | 1005 | ## 6.8.3 1006 | 1007 | p 站代码又变了,获取画师名的代码做了相应的修改。现在其实是更简单了,挺好的。 1008 | 1009 | ## 6.8.4 1010 | 1011 | ** 本脚本版未来可能不再有大的更新,只会修复 bug 和维护基础功能。希望用户尽快迁移到 Chrome 扩展版. 1012 | 1013 | - 下载书签作品时会倒序下载。 1014 | 1015 | - 添加提示,提醒用户安装扩展版。 1016 | 1017 | ## 6.8.5 1018 | 1019 | 添加说明,提醒用户迁移到扩展版。 1020 | 1021 | ## 6.8.6 1022 | 1023 | 由 phenixl 提交的 pull: 1024 | 增加XMP Sidecar 文件保存TAG,保存前整理TAG 1025 | https://github.com/xuejianxianzun/XZPixivDownloader/pull/27 1026 | 1027 | ## 6.8.7 1028 | 1029 | chrome 扩展版之前被下架了,现在重新上架,url 变了。这次把代码里的安装地址改为新的地址。 1030 | 1031 | ## 6.8.8 1032 | 1033 | chrome 扩展版又被下架了。所以把安装地址改为离线安装的教程地址。 1034 | 1035 | ## 6.8.9 1036 | 1037 | - 适配作品页面新的 url 格式 1038 | 1039 | 这个问题影响很大,所以对脚本版做了适应。 1040 | 1041 | ## 6.9.0 1042 | 1043 | 发现有些人在手机浏览器里使用脚本版。所以把脚本版获取 userId 的代码也适配了手机版页面。 1044 | --------------------------------------------------------------------------------