您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically download images and description of some model site. 需要在油猴脚本中设置-通用开启高级模式,然后在下载 BETA中下载模式选择浏览器api,然后增加json进白名单(或者不想下json也可以不设置)。支持模之屋、bowlroll、booth。
// ==UserScript== // @name 自动下载模型站预览与简介 // @namespace http://tampermonkey.net/ // @version 1.0 // @description Automatically download images and description of some model site. 需要在油猴脚本中设置-通用开启高级模式,然后在下载 BETA中下载模式选择浏览器api,然后增加json进白名单(或者不想下json也可以不设置)。支持模之屋、bowlroll、booth。 // @author SMatsuri // @match *.aplaybox.com/details/model/* // @match *bowlroll.net/file/* // @match *booth.pm/* // @grant GM_download // @grant GM_xmlhttpRequest // @license MIT // ==/UserScript== (function () { 'use strict'; // 创建下载按钮 const button = document.createElement('button'); button.innerText = '下载图片和简介'; button.id = 'downloadBtn'; // 添加样式,使按钮位于页面右下角 const style = document.createElement('style'); style.innerHTML = ` #downloadBtn { position: fixed; bottom: 20px; right: 20px; padding: 10px 20px; background-color: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; z-index: 10000; } #downloadBtn:hover { background-color: #45a049; } `; document.head.appendChild(style); document.body.appendChild(button); // 当前网站类型 const currentSite = window.location.hostname.includes('aplaybox.com') ? 'aplaybox' : window.location.hostname.includes('bowlroll.net') ? 'bowlroll' : window.location.hostname.includes('booth.pm') ? 'booth' : 'unknown'; // 保存工作详情 let Details = null; // 提取 URL 中的数字 ID,例如 https://bowlroll.net/file/326016 提取为 326016 function extractIdFromUrl(url) { const match = url.match(/\/file\/(\d+)/); // 匹配 URL 中的文件 ID return match ? match[1] : 'No_ID'; // 如果匹配成功,则返回文件 ID,否则返回 "No_ID" } let currentId = null; // 获取当前页面的数字 ID if (currentSite === 'bowlroll' || currentSite === 'booth'){ currentId = extractIdFromUrl(window.location.href); } const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this.addEventListener('load', function() { if (currentSite === 'aplaybox') { if (url.includes('getWorkDetails')) { // 检查是否是 getWorkDetails 请求 try { const response = JSON.parse(this.responseText); // 解析 JSON 响应 if (response.status === "success" && response.code === 200 && response.data && response.data.result && response.data.result.data) { Details = response.data.result.data; // 存储工作详情 console.log('Aplaybox Work details captured:', Details); } } catch (e) { console.error('解析 Aplaybox 响应失败:', e); } } } }); originalOpen.apply(this, arguments); }; // 按钮点击事件处理 button.addEventListener('click', function() { if (currentSite === 'aplaybox') { if (Details) { handleAplaybox(Details); } else { alert('工作详情尚未加载,或请求尚未捕获。请稍后再试。'); } } else if (currentSite === 'bowlroll') { handleBowlroll(); } else if (currentSite === 'booth') { handleBooth(); } else { alert('当前网站不受支持。'); } }); // 处理 Aplaybox 的下载 function handleAplaybox(data) { const workName = sanitizeFileName(data.work_name || "Unnamed_Work"); const introduction = 'Aplaybox\n\n' + decodeUnicode(data.introduction).replace(/\n/g, '\r\n'); const coverUrl = data.cover; const previewImages = data.preview_images; // Step 1: 下载 JSON 文件 const jsonData = JSON.stringify(data, null, 2); downloadFile(workName + '/metadata.json', jsonData, 'application/json'); // Step 2: 下载简介 downloadFile(workName + '/readme.txt', introduction, 'text/plain'); // 创建一个 Set 用于存储已下载的图片 URL const downloadedImages = new Set(); // Step 3: 下载封面图片 downloadImageAplaybox(coverUrl, workName + '/preview0.jpg'); downloadedImages.add(coverUrl); // 添加到已下载集合中 // Step 4: 下载预览图片 previewImages.forEach((imgUrl, index) => { // 检查图片 URL 是否已经下载过,避免重复下载 if (imgUrl && !downloadedImages.has(imgUrl)) { downloadedImages.add(imgUrl); // 添加到已下载集合中 downloadImageAplaybox(imgUrl, `${workName}/preview${index + 1}.jpg`); } }); } // 处理 BowlRoll 的下载 function handleBowlroll() { // 提取 meta 标签中的信息 const title = document.querySelector('meta[property="og:title"]')?.getAttribute('content') || 'No Title'; const description = document.querySelector('meta[name="description"]')?.getAttribute('content') || document.querySelector('meta[property="og:description"]')?.getAttribute('content') || 'No Description'; const imageUrl = document.querySelector('meta[property="og:image"]')?.getAttribute('content') || ''; const workName = sanitizeFileName(title); // 下载并合并文件 downloadBowlrolldata(workName, description); downloadImage(imageUrl, workName + '/preview0.jpg'); } // 使用 GM_xmlhttpRequest 代替 GM_download 来获取 JSON/二进制内容并处理 function downloadBowlrolldata(workName, introduction) { // 获取 message 内容 GM_xmlhttpRequest({ method: 'GET', url: 'https://bowlroll.net/api/file/' + currentId + '/message', responseType: 'json', // 我们假设 API 返回的是 JSON 格式 onload: function(response) { if (response.status === 200) { const messageData = response.response; // 获取 message 数据 const messageText = decodeUnicode(messageData.message); // 解码 message 字段 // 继续获取 tags 内容 GM_xmlhttpRequest({ method: 'GET', url: 'https://bowlroll.net/api/file/' + currentId + '/tags', responseType: 'json', // 我们假设 API 返回的是 JSON 格式 onload: function(response) { if (response.status === 200) { const tagsData = response.response.tags; // 获取 tags 数组 const tagsText = extractTags(tagsData); // 提取并解码 tags 的 name 字段 // 合并 messageText、tagsText 和 introduction const combinedText = `Bowlroll\n\n${introduction}\n\n---\n\nMessage:\n${messageText}\n\nTags:\n${tagsText}`; // 下载合并后的文件 downloadFile(workName + '/readme.txt', combinedText, 'text/plain'); } else { console.error('下载 tags 时出错,状态码:', response.status); } }, onerror: function(err) { console.error('下载 tags 时发生错误:', err); } }); } else { console.error('下载 message 时出错,状态码:', response.status); } }, onerror: function(err) { console.error('下载 message 时发生错误:', err); } }); } function handleBooth() { // 提取标题作为工作名称 const title = document.querySelector('meta[property="og:title"]')?.getAttribute('content') || 'No Title'; const workName = sanitizeFileName(title); // 清理标题作为文件夹名 // 提取完整的简介内容,包括所有 <p> 和 <section> 内的文本 const descriptionElement = document.querySelector('.js-market-item-detail-description'); let introduction = 'Booth\n\n'; if (descriptionElement) { // 遍历包含介绍内容的 <p>、<section> 及其他相关元素,提取其文本 const descriptionParts = descriptionElement.querySelectorAll('p, section'); descriptionParts.forEach(part => { introduction += part.innerText.trim() + '\n\n'; // 每个部分用换行符分隔 }); } else { introduction = 'No Description Available'; } const descriptionElement2 = document.querySelector('.my-40'); if (descriptionElement) { // 遍历包含介绍内容的 <p>、<section> 及其他相关元素,提取其文本 const descriptionParts = descriptionElement2.querySelectorAll('p, section'); descriptionParts.forEach(part => { introduction += part.innerText.trim() + '\n\n'; // 每个部分用换行符分隔 }); } // 下载简介 downloadFile(workName + '/readme.txt', introduction, 'text/plain'); GM_download({ url: window.location.href + '.json', name: workName + '/metadata.json', onerror: function(err) { console.error('下载文件时出错:', err); }, ontimeout: function() { console.error('下载文件超时'); }, onprogress: function(progress) { console.log('下载进度:', progress); } }); // 创建一个 Set 用于存储已下载的图片 URL const downloadedImages = new Set(); // 提取图片链接并下载 const images = document.querySelectorAll('.market-item-detail-item-image'); // 获取所有图片元素 images.forEach((imgElement, index) => { const imageUrl = imgElement.getAttribute('data-origin'); // 获取原始图片链接 // 检查图片 URL 是否已经下载过,避免重复下载 if (imageUrl && !downloadedImages.has(imageUrl)) { downloadedImages.add(imageUrl); // 添加到已下载集合中 downloadImage(imageUrl, `${workName}/preview${index + 1}.jpg`); // 下载图片 } }); } // 提取并解码 tags 中的 name 字段 function extractTags(tags) { return tags.map(tag => decodeUnicode(tag.name)).join(', '); } // 解码 Unicode 字符 function decodeUnicode(str) { return unescape(str.replace(/\\u/g, '%u')); } // 函数:清理文件名中的非法字符 function sanitizeFileName(fileName) { // 移除不允许出现在文件名中的字符,替换为下划线 return fileName.replace(/[\/\\?%*:|"<>。. ]/g, '_'); } // 使用 GM_download 下载文件 function downloadFile(filename, content, type) { const blob = new Blob([content], { type }); const url = URL.createObjectURL(blob); // 使用 GM_download 进行下载 GM_download({ url: url, name: filename, onerror: function(err) { console.error('下载文件时出错:', err); console.error(`文件名: ${filename}`); console.error(`URL: ${url}`); }, ontimeout: function() { console.error('下载文件超时'); }, onprogress: function(progress) { console.log('下载进度:', progress); } }); } // 下载图片的函数 function downloadImage(url, filename) { GM_download({ url: url, name: filename, onerror: function(err) { console.error('下载图片时出错:', err); }, ontimeout: function() { console.error('下载图片超时'); }, onprogress: function(progress) { console.log('下载进度:', progress); } }); } function downloadImageAplaybox(url, filename) { GM_xmlhttpRequest({ method: 'GET', url: url, responseType: 'blob', // 下载图片作为二进制数据 headers: { // 添加 Cookie,如果需要的话 'Cookie': document.cookie, // 自动携带当前页面的所有 Cookies 'User-Agent': navigator.userAgent, // 模拟普通浏览器请求 'Referer': window.location.href, // 设置 Referer }, onload: function(response) { if (response.status === 200) { // 创建 Blob 对象并下载 const blob = response.response; const blobUrl = URL.createObjectURL(blob); GM_download({ url: blobUrl, name: filename, saveAs: false, onload: function() { console.log('图片下载成功:', filename); }, onerror: function(err) { console.error('下载图片时出错:', err); } }); } else { console.error('服务器返回错误状态码:', response.status); } }, onerror: function(err) { console.error('下载图片时发生错误:', err); } }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址