🏠 Home 

Pixiv Show Request Price

For each artwork on Pixiv, show the request price if available and sort artworks by price.


Install this script?
  1. // ==UserScript==
  2. // @name Pixiv Show Request Price
  3. // @author MahdeenSky
  4. // @namespace http://tampermonkey.net/
  5. // @version 1.0
  6. // @description For each artwork on Pixiv, show the request price if available and sort artworks by price.
  7. // @match https://www.pixiv.net/request/creators/works/illust
  8. // @match https://www.pixiv.net/request/creators/works/illust?*
  9. // @match https://www.pixiv.net/bookmark_new_illust.php
  10. // @match https://www.pixiv.net/discovery
  11. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  12. // @grant none
  13. // @license GNU GPLv3
  14. // ==/UserScript==
  15. (function () {
  16. "use strict";
  17. const button = document.createElement("button");
  18. button.innerText = "Show Request Price (0/0)";
  19. button.style.position = "fixed";
  20. button.style.bottom = "10px";
  21. button.style.left = "10px";
  22. button.style.zIndex = "9999";
  23. button.style.padding = "10px";
  24. button.style.backgroundColor = "blue";
  25. button.style.color = "white";
  26. button.style.border = "none";
  27. button.style.borderRadius = "5px";
  28. button.style.cursor = "pointer";
  29. document.body.appendChild(button);
  30. const sortButton = document.createElement("button");
  31. sortButton.innerText = "Sort by Price";
  32. sortButton.style.position = "fixed";
  33. sortButton.style.bottom = "50px";
  34. sortButton.style.left = "10px";
  35. sortButton.style.zIndex = "9999";
  36. sortButton.style.padding = "10px";
  37. sortButton.style.backgroundColor = "green";
  38. sortButton.style.color = "white";
  39. sortButton.style.border = "none";
  40. sortButton.style.borderRadius = "5px";
  41. sortButton.style.cursor = "pointer";
  42. document.body.appendChild(sortButton);
  43. const MAX_PARALLEL_IFRAMES = 2;
  44. let activeIframes = 0;
  45. let globalIndex = 0;
  46. let artistUrls = [];
  47. let artworks = [];
  48. let updatedCount = 0;
  49. function updateButtonText() {
  50. button.innerText = `Show Request Price (${updatedCount}/${artworks.length})`;
  51. }
  52. function waitForRequestPriceElement(wrapperDiv, iframe, artistUrl, artwork) {
  53. iframe.addEventListener('load', () => {
  54. let requestPriceElement = iframe.contentDocument.querySelector("p.sc-a5e65548-7");
  55. if (requestPriceElement) {
  56. const requestPrice = requestPriceElement.innerText;
  57. console.log(
  58. "######################## " +
  59. artistUrl +
  60. " ##############" +
  61. requestPrice
  62. );
  63. const priceElement = document.createElement("div");
  64. priceElement.classList.add("request-price");
  65. priceElement.innerText = `Request Price: ${requestPrice}`;
  66. priceElement.style.backgroundColor = "#f0f0f0";
  67. priceElement.style.color = "#333";
  68. priceElement.style.padding = "10px";
  69. priceElement.style.marginBottom = "10px";
  70. priceElement.style.border = "1px solid #ccc";
  71. priceElement.style.borderRadius = "5px";
  72. priceElement.style.fontSize = "14px";
  73. priceElement.style.fontWeight = "bold";
  74. priceElement.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)";
  75. priceElement.style.opacity = "0";
  76. priceElement.style.transition = "opacity 0.5s ease-in-out";
  77. artwork.insertBefore(priceElement, artwork.firstChild);
  78. requestAnimationFrame(() => {
  79. priceElement.style.opacity = "1";
  80. });
  81. updatedCount++;
  82. updateButtonText();
  83. } else {
  84. console.log("Request price element not found, skipping...");
  85. }
  86. activeIframes--;
  87. console.log("Active iframes after decrement: " + activeIframes);
  88. processArtist();
  89. // reload the iframe then remove the wrapper div
  90. iframe.src = "about:blank";
  91. wrapperDiv.innerHTML = "<iframe style='display: none;'></iframe>";
  92. setTimeout(() => {
  93. wrapperDiv.remove();
  94. }, 1000);
  95. });
  96. }
  97. function processArtist() {
  98. if (globalIndex >= artistUrls.length) {
  99. console.log("All artists processed");
  100. return; // All artists processed
  101. }
  102. if (activeIframes >= MAX_PARALLEL_IFRAMES) {
  103. console.log("Max parallel iframes reached, retrying...");
  104. setTimeout(processArtist, 100); // Retry after 100ms
  105. return;
  106. }
  107. activeIframes++;
  108. console.log("Processing " + artistUrls[globalIndex]);
  109. const artistUrl = artistUrls[globalIndex];
  110. const artwork = artworks[globalIndex];
  111. const wrapperDiv = document.createElement("div");
  112. const iframe = document.createElement("iframe");
  113. iframe.style.display = "none";
  114. iframe.src = artistUrl + "/request";
  115. console.log("Visiting " + iframe.src);
  116. globalIndex++;
  117. wrapperDiv.appendChild(iframe);
  118. document.body.appendChild(wrapperDiv);
  119. waitForRequestPriceElement(wrapperDiv, iframe, artistUrl, artwork);
  120. }
  121. function scrapeArtworks() {
  122. // do a case by case check for different kind of css selectors for artworks
  123. const selectors = ["li.PKpFw", "li.kFAPOq"];
  124. let selector = null;
  125. if (document.querySelector(selectors[0])) {
  126. selector = selectors[0];
  127. } else if (document.querySelector(selectors[1])) {
  128. selector = selectors[1];
  129. } else {
  130. console.error("No artworks found");
  131. return { artistUrls: [], artworks: [] };
  132. }
  133. const artworks = document.querySelectorAll(selector);
  134. const artistUrls = [];
  135. artworks.forEach((artwork) => {
  136. // Check if the artwork already has the price element with the class "request-price"
  137. const existingPriceElement = artwork.querySelector('.request-price');
  138. if (existingPriceElement) {
  139. return; // Skip this artwork if it already has the price
  140. }
  141. let selector = "a.sc-1rx6dmq-2";
  142. if (document.querySelector("a.pPtWa")) {
  143. selector = "a.pPtWa";
  144. }
  145. const artistLink = artwork.querySelector(selector);
  146. const artistUrl = artistLink.href;
  147. artistUrls.push(artistUrl);
  148. });
  149. return { artistUrls, artworks };
  150. }
  151. function getPrices() {
  152. let scrapedData = scrapeArtworks();
  153. artistUrls = scrapedData.artistUrls;
  154. artworks = scrapedData.artworks;
  155. updateButtonText(); // Update button text with initial counts
  156. // Start processing up to MAX_PARALLEL_IFRAMES artists initially
  157. for (let i = 0; i < MAX_PARALLEL_IFRAMES; i++) {
  158. setTimeout(processArtist, 300 * i);
  159. }
  160. }
  161. function sortArtworksByPrice() {
  162. const artworksContainer = document.querySelector("ul.sc-e6de33c8-0");
  163. const artworksArray = Array.from(document.querySelectorAll("li.sc-9111aad9-0"));
  164. const sortedArtworks = artworksArray.sort((a, b) => {
  165. const priceA = parseFloat(a.querySelector(".request-price").innerText.replace(/[^0-9.-]+/g, ""));
  166. const priceB = parseFloat(b.querySelector(".request-price").innerText.replace(/[^0-9.-]+/g, ""));
  167. return priceA - priceB;
  168. });
  169. sortedArtworks.forEach((artwork) => {
  170. artworksContainer.appendChild(artwork);
  171. });
  172. }
  173. button.addEventListener("click", getPrices);
  174. sortButton.addEventListener("click", sortArtworksByPrice);
  175. })();