pixiv获取原图

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

  1. // ==UserScript==
  2. // @name pixiv获取原图
  3. // @namespace https://github.com/MuXia-0326/twitter-auto-original-picture
  4. // @version 1.7
  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.  
  15. const css = `
  16. .pixiv-Btn {
  17. z-index: 1000;
  18. position: relative;
  19. display: inline-block;
  20. margin-right: 5px;
  21. padding: 10px;
  22. text-align: center;
  23. font-size: 18px;
  24. letter-spacing: 1px;
  25. text-decoration: none;
  26. color: rgb(0, 150, 250);
  27. background: transparent;
  28. cursor: pointer;
  29. transition: ease-out 0.5s;
  30. border: 2px solid rgb(0, 150, 250);
  31. border-radius: 10px;
  32. box-shadow: inset 0 0 0 0 rgb(0, 150, 250);
  33. }
  34. .pixiv-Btn:hover {
  35. color: white;
  36. box-shadow: inset 0 -100px 0 0 rgb(0, 150, 250);
  37. }
  38. .pixiv-Btn:active {
  39. transform: scale(0.9);
  40. }
  41. .pixiv-Btn:hover svg {
  42. fill: white;
  43. }
  44. .pixiv-Btn:active svg, .pixiv-Btn svg {
  45. fill: rgb(0, 150, 250);
  46. }
  47.  
  48.  
  49. .Btn {
  50. position: absolute;
  51. right: 0px;
  52. bottom: 0px;
  53. }
  54. .svgClass {
  55. display: flex;
  56. }
  57.  
  58. .share-btn {
  59. display:none;
  60. }
  61. `;
  62.  
  63. let styleTag = document.createElement('style');
  64. styleTag.innerText = css;
  65. document.head.append(styleTag);
  66.  
  67. function ILog() {
  68. this.prefix = '';
  69.  
  70. this.v = function (value) {
  71. if (level <= this.LogLevel.Verbose) {
  72. console.log(this.prefix + value);
  73. }
  74. };
  75.  
  76. this.i = function (info) {
  77. if (level <= this.LogLevel.Info) {
  78. console.info(this.prefix + info);
  79. }
  80. };
  81.  
  82. this.w = function (warning) {
  83. if (level <= this.LogLevel.Warning) {
  84. console.warn(this.prefix + warning);
  85. }
  86. };
  87.  
  88. this.e = function (error) {
  89. if (level <= this.LogLevel.Error) {
  90. console.error(this.prefix + error);
  91. }
  92. };
  93.  
  94. this.d = function (element) {
  95. if (level <= this.LogLevel.Verbose) {
  96. console.log(element);
  97. }
  98. };
  99.  
  100. this.setLogLevel = function (logLevel) {
  101. level = logLevel;
  102. };
  103.  
  104. this.LogLevel = {
  105. Verbose: 0,
  106. Info: 1,
  107. Warning: 2,
  108. Error: 3,
  109. };
  110.  
  111. let level = this.LogLevel.Warning;
  112. }
  113. var iLog = new ILog();
  114.  
  115. // let pixiv_proxy = 'https://i.pixiv.cat';
  116. let pixiv_proxy = 'https://pixiv.mossia.top';
  117. let g_getArtworkUrl = '/ajax/illust/#id#/pages';
  118.  
  119. let share_url = '';
  120. let share_url_two = '';
  121. let userName = '';
  122.  
  123. // 当前页面类型
  124. let g_pageType = -1;
  125.  
  126. // 页面相关的一些预定义,包括处理页面元素等
  127. let PageType = {
  128. // 作品详情页
  129. Artwork: 0,
  130.  
  131. // 总数
  132. PageTypeCount: 1,
  133. };
  134.  
  135. /* Pages 必须实现的函数
  136. * PageTypeString: string,字符串形式的 PageType
  137. * bool CheckUrl: function(string url),用于检查一个 url 是否是当前页面的目标 url
  138. * ProcessPageElements: function(),处理页面(寻找图片元素、添加按钮)
  139. */
  140. let Pages = {};
  141.  
  142. Pages[PageType.Artwork] = {
  143. PageTypeString: 'ArtworkPage',
  144. CheckUrl: function (url) {
  145. return /^https:\/\/www.pixiv.net\/artworks\/.*/.test(url) || /^https:\/\/www.pixiv.net\/en\/artworks\/.*/.test(url);
  146. },
  147. ProcessPageElements: function () {
  148. if (userName === '') {
  149. getUserName();
  150. }
  151.  
  152. // 动图不处理
  153. if (document.querySelector('main figure canvas')) {
  154. return;
  155. }
  156.  
  157. // 未加载完不处理
  158. if (!document.querySelector('main figure')) {
  159. return;
  160. }
  161.  
  162. let allImage = document.querySelector('main figure').parentNode.querySelector('section + button');
  163. if (allImage) {
  164. allImage.click();
  165. }
  166.  
  167. let matched = location.href.match(/artworks\/(\d+)/);
  168. if (!matched) {
  169. return;
  170. }
  171.  
  172. let pid = matched[1];
  173. let url = g_getArtworkUrl.replace('#id#', pid);
  174.  
  175. let original = [];
  176.  
  177. //生成按钮
  178. let divImages = document.querySelectorAll('main figure div:first-child div[role="presentation"]');
  179. divImages.forEach((e, i) => {
  180. let _this = e;
  181. let image = _this.querySelector('a').parentNode;
  182. if (image.querySelector('.Btn') && image.querySelector('.Btn').getAttribute('data-pid') === pid) {
  183. return;
  184. }
  185.  
  186. fetch(url, {
  187. method: 'GET',
  188. })
  189. .then((response) => response.json())
  190. .then((json) => {
  191. iLog.i('Got artwork urls:');
  192.  
  193. if (json.error === true) {
  194. iLog.e('Server responsed an error: ' + json.message);
  195. return;
  196. }
  197.  
  198. for (let i = 0; i < json.body.length; i++) {
  199. original.push(json.body[i].urls.original);
  200. }
  201. })
  202. .catch((error) => {
  203. iLog.e('Request image urls failed!');
  204. if (error) {
  205. iLog.e(error);
  206. }
  207. });
  208.  
  209. let btns = image.querySelectorAll('.Btn');
  210. if (btns.length > 0) {
  211. btns.forEach((btn) => btn.remove());
  212. }
  213. let div = document.createElement('div');
  214.  
  215. div.innerHTML = `
  216. <div class="Btn" data-pid=${pid}>
  217. <button class="pixiv-Btn" id="cp_${i}">
  218. <div class="svgClass">
  219. <svg t="1694962361717" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5412" width="20" height="20">
  220. <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>
  221. <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>
  222. </svg>
  223. </div>
  224. </button>
  225. <button class="pixiv-Btn" id="download_${i}">
  226. <div class="svgClass">
  227. <svg t="1694962091616" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4129" id="mx_n_1694962091617" width="20" height="20">
  228. <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>
  229. <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>
  230. </svg>
  231. </div>
  232. </button>
  233. <button class="pixiv-Btn share-btn" id="share_${i}">
  234. <div class="svgClass">
  235. <svg t="1713618483987" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2790" width="20" height="20">
  236. <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>
  237. </svg>
  238. </div>
  239. </button>
  240. </div>
  241. `;
  242.  
  243. image.appendChild(div);
  244.  
  245. document.getElementById(`cp_${i}`).addEventListener('click', function () {
  246. let newUrl = original[i].replace('https://i.pximg.net', pixiv_proxy);
  247. navigator.clipboard.writeText(newUrl);
  248. });
  249.  
  250. document.getElementById(`download_${i}`).addEventListener('click', function () {
  251. // 点击喜欢按钮
  252. let likeDiv = document.querySelector('main section section div.sc-a74b10e0-3.fCOpda');
  253. if (likeDiv) {
  254. let a = likeDiv.querySelector('a');
  255. if (!a) {
  256. likeDiv.querySelector('button').click();
  257. }
  258. }
  259.  
  260. let newUrl = original[i];
  261.  
  262. GM_xmlhttpRequest({
  263. method: 'GET',
  264. url: newUrl,
  265. headers: {
  266. Referer: 'https://www.pixiv.net/',
  267. },
  268. responseType: 'blob', // 添加这一行
  269. onload: function (response) {
  270. if (response.status === 200) {
  271. var blobUrl = URL.createObjectURL(response.response);
  272. GM_download(blobUrl, newUrl.substring(newUrl.lastIndexOf('/') + 1));
  273. } else {
  274. console.error('Download failed:', response.statusText);
  275. }
  276. },
  277. });
  278.  
  279. GM_xmlhttpRequest({
  280. method: 'POST',
  281. url: 'https://api.mossia.top/add/pPidQueue',
  282. headers: {
  283. 'Content-Type': 'application/json',
  284. },
  285. data: JSON.stringify({
  286. pidList: [pid],
  287. createBy: userName,
  288. }),
  289. onload: function (response) {
  290. let result = JSON.parse(response.responseText);
  291. },
  292. onerror: function (error) {
  293. console.error('Request failed:', error);
  294. },
  295. });
  296. });
  297.  
  298. document.getElementById(`share_${i}`).addEventListener('click', function () {
  299. let newUrl = original[i].replace('https://i.pximg.net', pixiv_proxy);
  300. GM_xmlhttpRequest({
  301. method: 'POST',
  302. url: share_url, // 目标 URL
  303. headers: {
  304. 'Content-Type': 'application/json',
  305. },
  306. data: JSON.stringify({ imageUrl: newUrl }),
  307. onload: function (response) {
  308. var responseData = JSON.parse(response.responseText);
  309. console.log('Received response:', responseData);
  310. },
  311. onerror: function (error) {
  312. console.error('Request failed:', error);
  313. },
  314. });
  315. GM_xmlhttpRequest({
  316. method: 'POST',
  317. url: share_url_two, // 目标 URL
  318. headers: {
  319. 'Content-Type': 'application/json',
  320. },
  321. data: JSON.stringify({ urls: [newUrl] }),
  322. onload: function (response) {
  323. var responseData = JSON.parse(response.responseText);
  324. console.log('Received response:', responseData);
  325. },
  326. onerror: function (error) {
  327. console.error('Request failed:', error);
  328. },
  329. });
  330. });
  331. });
  332. },
  333. };
  334.  
  335. function main() {
  336. // 匹配当前页面
  337. for (let i = 0; i < PageType.PageTypeCount; i++) {
  338. if (Pages[i].CheckUrl(location.href)) {
  339. g_pageType = i;
  340. break;
  341. }
  342. }
  343.  
  344. if (g_pageType >= 0) {
  345. iLog.i('当前页面类型:' + Pages[g_pageType].PageTypeString);
  346. } else {
  347. iLog.i('当前页面类型:未知');
  348. clearInterval(mainInterval);
  349. return;
  350. }
  351.  
  352. // 执行操作
  353. Pages[g_pageType].ProcessPageElements();
  354. }
  355.  
  356. function getUserName() {
  357. var div = document.querySelector('button.flex.gap-8.items-center.p-0.text-text3');
  358. let nameDiv = div.querySelector('div.sc-f0b66801-0.klDrpf');
  359. userName = nameDiv.getAttribute('title');
  360. }
  361.  
  362. let mainInterval = setInterval(main, 200);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址