🏠 返回首頁 

Greasy Fork is available in English.

pixiv获取原图

pixiv页面生成按钮用于复制原图链接和下载原图


安装此脚本?
  1. // ==UserScript==
  2. // @name pixiv获取原图
  3. // @namespace https://github.com/MuXia-0326/twitter-auto-original-picture
  4. // @version 1.5
  5. // @description pixiv页面生成按钮用于复制原图链接和下载原图
  6. // @author Mossia
  7. // @icon https://raw.githubusercontent.com/MuXia-0326/drawio/master/angri.png
  8. // @match *://www.pixiv.net/*
  9. // @grant unsafeWindow
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_download
  12. // @license MIT
  13. // ==/UserScript==
  14. const css = `
  15. .pixiv-Btn {
  16. z-index: 1000;
  17. position: relative;
  18. display: inline-block;
  19. margin-right: 5px;
  20. padding: 10px;
  21. text-align: center;
  22. font-size: 18px;
  23. letter-spacing: 1px;
  24. text-decoration: none;
  25. color: rgb(0, 150, 250);
  26. background: transparent;
  27. cursor: pointer;
  28. transition: ease-out 0.5s;
  29. border: 2px solid rgb(0, 150, 250);
  30. border-radius: 10px;
  31. box-shadow: inset 0 0 0 0 rgb(0, 150, 250);
  32. }
  33. .pixiv-Btn:hover {
  34. color: white;
  35. box-shadow: inset 0 -100px 0 0 rgb(0, 150, 250);
  36. }
  37. .pixiv-Btn:active {
  38. transform: scale(0.9);
  39. }
  40. .pixiv-Btn:hover svg {
  41. fill: white;
  42. }
  43. .pixiv-Btn:active svg, .pixiv-Btn svg {
  44. fill: rgb(0, 150, 250);
  45. }
  46. .Btn {
  47. position: absolute;
  48. right: 0px;
  49. bottom: 0px;
  50. }
  51. .svgClass {
  52. display: flex;
  53. }
  54. .share-btn {
  55. display:none;
  56. }
  57. `;
  58. let styleTag = document.createElement('style');
  59. styleTag.innerText = css;
  60. document.head.append(styleTag);
  61. function ILog() {
  62. this.prefix = '';
  63. this.v = function (value) {
  64. if (level <= this.LogLevel.Verbose) {
  65. console.log(this.prefix + value);
  66. }
  67. };
  68. this.i = function (info) {
  69. if (level <= this.LogLevel.Info) {
  70. console.info(this.prefix + info);
  71. }
  72. };
  73. this.w = function (warning) {
  74. if (level <= this.LogLevel.Warning) {
  75. console.warn(this.prefix + warning);
  76. }
  77. };
  78. this.e = function (error) {
  79. if (level <= this.LogLevel.Error) {
  80. console.error(this.prefix + error);
  81. }
  82. };
  83. this.d = function (element) {
  84. if (level <= this.LogLevel.Verbose) {
  85. console.log(element);
  86. }
  87. };
  88. this.setLogLevel = function (logLevel) {
  89. level = logLevel;
  90. };
  91. this.LogLevel = {
  92. Verbose: 0,
  93. Info: 1,
  94. Warning: 2,
  95. Error: 3,
  96. };
  97. let level = this.LogLevel.Warning;
  98. }
  99. var iLog = new ILog();
  100. // let pixiv_proxy = 'https://i.pixiv.cat';
  101. let pixiv_proxy = 'https://pixiv.mossia.top';
  102. let g_getArtworkUrl = '/ajax/illust/#id#/pages';
  103. let share_url = '';
  104. let share_url_two = '';
  105. let userName = '';
  106. // 当前页面类型
  107. let g_pageType = -1;
  108. // 页面相关的一些预定义,包括处理页面元素等
  109. let PageType = {
  110. // 作品详情页
  111. Artwork: 0,
  112. // 总数
  113. PageTypeCount: 1,
  114. };
  115. /* Pages 必须实现的函数
  116. * PageTypeString: string,字符串形式的 PageType
  117. * bool CheckUrl: function(string url),用于检查一个 url 是否是当前页面的目标 url
  118. * ProcessPageElements: function(),处理页面(寻找图片元素、添加按钮)
  119. */
  120. let Pages = {};
  121. Pages[PageType.Artwork] = {
  122. PageTypeString: 'ArtworkPage',
  123. CheckUrl: function (url) {
  124. return /^https:\/\/www.pixiv.net\/artworks\/.*/.test(url) || /^https:\/\/www.pixiv.net\/en\/artworks\/.*/.test(url);
  125. },
  126. ProcessPageElements: function () {
  127. if (userName === '') {
  128. getUserName();
  129. }
  130. // 动图不处理
  131. if (document.querySelector('main figure canvas')) {
  132. return;
  133. }
  134. // 未加载完不处理
  135. if (!document.querySelector('main figure')) {
  136. return;
  137. }
  138. let allImage = document.querySelector('main figure').parentNode.querySelector('section + button');
  139. if (allImage) {
  140. allImage.click();
  141. }
  142. let matched = location.href.match(/artworks\/(\d+)/);
  143. if (!matched) {
  144. return;
  145. }
  146. let pid = matched[1];
  147. let url = g_getArtworkUrl.replace('#id#', pid);
  148. let original = [];
  149. //生成按钮
  150. let divImages = document.querySelectorAll('main figure div:first-child div[role="presentation"]');
  151. divImages.forEach((e, i) => {
  152. let _this = e;
  153. let image = _this.querySelector('a').parentNode;
  154. if (image.querySelector('.Btn') && image.querySelector('.Btn').getAttribute('data-pid') === pid) {
  155. return;
  156. }
  157. fetch(url, {
  158. method: 'GET',
  159. })
  160. .then((response) => response.json())
  161. .then((json) => {
  162. iLog.i('Got artwork urls:');
  163. if (json.error === true) {
  164. iLog.e('Server responsed an error: ' + json.message);
  165. return;
  166. }
  167. for (let i = 0; i < json.body.length; i++) {
  168. original.push(json.body[i].urls.original);
  169. }
  170. })
  171. .catch((error) => {
  172. iLog.e('Request image urls failed!');
  173. if (error) {
  174. iLog.e(error);
  175. }
  176. });
  177. let btns = image.querySelectorAll('.Btn');
  178. if (btns.length > 0) {
  179. btns.forEach((btn) => btn.remove());
  180. }
  181. let div = document.createElement('div');
  182. div.innerHTML = `
  183. <div class="Btn" data-pid=${pid}>
  184. <button class="pixiv-Btn" id="cp_${i}">
  185. <div class="svgClass">
  186. <svg t="1694962361717" class="icon" viewBox="0 0 #### ####" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5412" width="20" height="20">
  187. <path d="M761.088 715.3152a38.7072 38.7072 0 0 1 0-77.4144 37.4272 37.4272 0 0 0 37.4272-37.4272V265.0112a37.4272 37.4272 0 0 0-37.4272-37.4272H425.6256a37.4272 37.4272 0 0 0-37.4272 37.4272 38.7072 38.7072 0 1 1-77.4144 0 115.0976 115.0976 0 0 1 114.8416-114.8416h335.4624a115.0976 115.0976 0 0 1 114.8416 114.8416v335.4624a115.0976 115.0976 0 0 1-114.8416 114.8416z" p-id="5413" ></path>
  188. <path d="M589.4656 883.0976H268.1856a121.1392 121.1392 0 0 1-121.2928-121.2928v-322.56a121.1392 121.1392 0 0 1 121.2928-121.344h321.28a121.1392 121.1392 0 0 1 121.2928 121.2928v322.56c1.28 67.1232-54.1696 121.344-121.2928 121.344zM268.1856 395.3152a43.52 43.52 0 0 0-43.8784 43.8784v322.56a43.52 43.52 0 0 0 43.8784 43.8784h321.28a43.52 43.52 0 0 0 43.8784-43.8784v-322.56a43.52 43.52 0 0 0-43.8784-43.8784z" p-id="5414" ></path>
  189. </svg>
  190. </div>
  191. </button>
  192. <button class="pixiv-Btn" id="download_${i}">
  193. <div class="svgClass">
  194. <svg t="1694962091616" class="icon" viewBox="0 0 #### ####" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4129" id="mx_n_1694962091617" width="20" height="20">
  195. <path d="M160 579.2a28.8 28.8 0 0 1 28.8 28.8v170.672c0 30.4 25.664 56.528 59.2 56.528h528c33.536 0 59.2-26.144 59.2-56.528V608a28.8 28.8 0 0 1 57.6 0v170.672c0 63.856-53.12 114.128-116.8 114.128h-528c-63.68 0-116.8-50.272-116.8-114.128V608a28.8 28.8 0 0 1 28.8-28.8z" p-id="4130"></path><path d="M540.8 176l0 464a28.8 28.8 0 0 1-57.6 0L483.2 176a28.8 28.8 0 0 1 57.6 0z" p-id="4131"></path>
  196. <path d="M331.632 459.632a28.8 28.8 0 0 1 40.736 0l160 160a28.8 28.8 0 0 1-40.736 40.736l-160-160a28.8 28.8 0 0 1 0-40.736z" p-id="4132"></path><path d="M692.368 459.632a28.8 28.8 0 0 0-40.736 0l-160 160a28.8 28.8 0 0 0 40.736 40.736l160-160a28.8 28.8 0 0 0 0-40.736z" p-id="4133"></path>
  197. </svg>
  198. </div>
  199. </button>
  200. <button class="pixiv-Btn share-btn" id="share_${i}">
  201. <div class="svgClass">
  202. <svg t="1713618483987" class="icon" viewBox="0 0 #### ####" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2790" width="20" height="20">
  203. <path d="M720.020242 809.16812c0-49.233308 39.919175-89.151459 89.151459-89.151459s89.150436 39.918151 89.150436 89.151459c0 49.227168-39.918151 89.159646-89.150436 89.159646S720.020242 858.397335 720.020242 809.16812zM571.433112 214.824717c0-49.234331 39.919175-89.152483 89.151459-89.152483 49.234331 0 89.152483 39.918151 89.152483 89.152483 0 49.232285-39.918151 89.151459-89.152483 89.151459C611.352287 303.976176 571.433112 264.057001 571.433112 214.824717zM125.674792 675.441443c0-82.07018 66.530252-148.586107 148.585083-148.586107 82.056877 0 148.58713 66.515926 148.58713 148.586107 0 82.071204-66.531276 148.58713-148.58713 148.58713C192.205045 824.028573 125.674792 757.511623 125.674792 675.441443zM66.240145 675.441443c0 114.89375 93.142353 208.027917 208.019731 208.027917 81.402985 0 151.8525-46.752814 186.03809-114.870214l200.360284 35.288714-0.073678 5.28026c0 82.07632 66.531276 148.594293 148.58713 148.594293s148.586107-66.517973 148.586107-148.594293c0-82.072227-66.530252-148.586107-148.586107-148.586107-59.507302 0-110.815875 34.927487-134.554532 85.436858l-195.454554-34.403554c2.059915-11.738345 3.119037-23.839965 3.119037-36.174897 0-54.311976-20.822235-103.748922-54.892191-140.779304l180.740434-180.755784c16.309454 6.152117 33.983999 9.503445 52.454676 9.503445 82.056877 0 148.58713-66.514903 148.58713-148.586107 0-82.07018-66.530252-148.58713-148.58713-148.58713-82.055854 0-148.585083 66.51695-148.585083 148.58713 0 41.674145 17.165961 79.32772 44.792159 106.317421L381.013225 496.92056c-31.211862-18.71934-67.703985-29.499871-106.753349-29.499871C159.382499 467.421712 66.240145 560.549739 66.240145 675.441443z" p-id="2791"></path>
  204. </svg>
  205. </div>
  206. </button>
  207. </div>
  208. `;
  209. image.appendChild(div);
  210. document.getElementById(`cp_${i}`).addEventListener('click', function () {
  211. let newUrl = original[i].replace('https://i.pximg.net', pixiv_proxy);
  212. navigator.clipboard.writeText(newUrl);
  213. });
  214. document.getElementById(`download_${i}`).addEventListener('click', function () {
  215. // 点击喜欢按钮
  216. let likeDiv = document.querySelector('main section section div.sc-181ts2x-3.cXSAgn');
  217. if (likeDiv) {
  218. let a = likeDiv.querySelector('a');
  219. if (!a) {
  220. likeDiv.querySelector('button').click();
  221. }
  222. }
  223. let newUrl = original[i];
  224. GM_xmlhttpRequest({
  225. method: 'GET',
  226. url: newUrl,
  227. headers: {
  228. Referer: 'https://www.pixiv.net/',
  229. },
  230. responseType: 'blob', // 添加这一行
  231. onload: function (response) {
  232. if (response.status === 200) {
  233. var blobUrl = URL.createObjectURL(response.response);
  234. GM_download(blobUrl, newUrl.substring(newUrl.lastIndexOf('/') + 1));
  235. } else {
  236. console.error('Download failed:', response.statusText);
  237. }
  238. },
  239. });
  240. GM_xmlhttpRequest({
  241. method: 'POST',
  242. url: 'https://api.mossia.top/add/pPidQueue',
  243. headers: {
  244. 'Content-Type': 'application/json',
  245. },
  246. data: JSON.stringify({
  247. pidList: [pid],
  248. createBy: userName,
  249. }),
  250. onload: function (response) {
  251. let r###lt = JSON.parse(response.responseText);
  252. },
  253. onerror: function (error) {
  254. console.error('Request failed:', error);
  255. },
  256. });
  257. });
  258. document.getElementById(`share_${i}`).addEventListener('click', function () {
  259. let newUrl = original[i].replace('https://i.pximg.net', pixiv_proxy);
  260. GM_xmlhttpRequest({
  261. method: 'POST',
  262. url: share_url, // 目标 URL
  263. headers: {
  264. 'Content-Type': 'application/json',
  265. },
  266. data: JSON.stringify({ imageUrl: newUrl }),
  267. onload: function (response) {
  268. var responseData = JSON.parse(response.responseText);
  269. console.log('Received response:', responseData);
  270. },
  271. onerror: function (error) {
  272. console.error('Request failed:', error);
  273. },
  274. });
  275. GM_xmlhttpRequest({
  276. method: 'POST',
  277. url: share_url_two, // 目标 URL
  278. headers: {
  279. 'Content-Type': 'application/json',
  280. },
  281. data: JSON.stringify({ urls: [newUrl] }),
  282. onload: function (response) {
  283. var responseData = JSON.parse(response.responseText);
  284. console.log('Received response:', responseData);
  285. },
  286. onerror: function (error) {
  287. console.error('Request failed:', error);
  288. },
  289. });
  290. });
  291. });
  292. },
  293. };
  294. function main() {
  295. // 匹配当前页面
  296. for (let i = 0; i < PageType.PageTypeCount; i++) {
  297. if (Pages[i].CheckUrl(location.href)) {
  298. g_pageType = i;
  299. break;
  300. }
  301. }
  302. if (g_pageType >= 0) {
  303. iLog.i('当前页面类型:' + Pages[g_pageType].PageTypeString);
  304. } else {
  305. iLog.i('当前页面类型:未知');
  306. clearInterval(mainInterval);
  307. return;
  308. }
  309. // 执行操作
  310. Pages[g_pageType].ProcessPageElements();
  311. }
  312. function getUserName() {
  313. var div = document.querySelectorAll('.sc-pkfh0q-0.kYDpSN .sc-1asno00-0.feBRRY');
  314. div.forEach((e, i) => {
  315. userName = e.getAttribute('title');
  316. console.log(userName);
  317. });
  318. }
  319. let mainInterval = setInterval(main, 200);