// ==UserScript== // @name AO3下载文章 // @namespace https://greasyfork.org/users/1384897 // @version 0.2 // @description AO3下载tag中的文章并打包成压缩包 // @author ✌ // @match https://archiveofourown.org/tags/*/works* // @match https://archiveofourown.org/works?* // @grant GM_xmlhttpRequest // @grant GM_download // @connect archiveofourown.org // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/514157/AO3%E4%B8%8B%E8%BD%BD%E6%96%87%E7%AB%A0.user.js // @updateURL https://update.greasyfork.icu/scripts/514157/AO3%E4%B8%8B%E8%BD%BD%E6%96%87%E7%AB%A0.meta.js // ==/UserScript== (function() { 'use strict'; const maxWorks = 1000; // 设置最大下载篇数 const delay = 4000; // 设置页面跳转的延迟,单位:毫秒 let worksProcessed = Number(localStorage.getItem('worksProcessed')) || 0; let zip = new JSZip(); let isDownloading = false; // 标志变量,是否正在下载 let downloadInterrupted = false; // 标志变量,用于控制是否中断下载 // 恢复未完成的 ZIP 进程 if (localStorage.getItem('ao3ZipData')) { const zipData = JSON.parse(localStorage.getItem('ao3ZipData')); Object.keys(zipData).forEach(filename => zip.file(filename, zipData[filename])); } // 创建下载按钮 const button = document.createElement('button'); button.innerText = `开始下载`; button.style.margin = "10px auto"; button.style.display = "block"; button.style.padding = "10px 20px"; button.style.backgroundColor = "#3498db"; button.style.color = "#000"; button.style.border = "none"; button.style.borderRadius = "5px"; button.style.cursor = "pointer"; button.style.fontSize = "16px"; button.style.textAlign = "center"; button.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.2)"; // 将按钮插入到 header 中 const header = document.querySelector('header#header'); if (header) { header.insertAdjacentElement('afterend', button); } button.addEventListener('click', () => { if (isDownloading) { // 如果正在下载,则停止下载 finalizeDownloadPartial(true); downloadInterrupted = true; console.log('下载已暂停'); button.innerText = '开始下载'; localStorage.clear(); worksProcessed = 0; isDownloading = false; location.reload(); } else { // 如果没有在下载,则开始下载 downloadInterrupted = false; startDownload(); } }); // 自动启动下载(用于翻页后的页面) if (localStorage.getItem('worksProcessed')) { startDownload(); } function startDownload() { console.log(`开始下载最多 ${maxWorks} 篇作品...`); isDownloading = true; button.innerText = `下载中 - 进度:${worksProcessed}/${maxWorks}`; updateButtonProgress(); processPage(window.location.href); } function processWorksWithDelay(links, index = 0) { if (downloadInterrupted) { isDownloading = false; console.log('下载已中断'); return; } if (index >= links.length || worksProcessed >= maxWorks) { checkForNextPage(document); return; } const link = links[index]; GM_xmlhttpRequest({ method: 'GET', url: link, onload: response => { if (downloadInterrupted) { isDownloading = false; console.log('下载已中断'); return; } const parser = new DOMParser(); const doc = parser.parseFromString(response.responseText, "text/html"); const title = doc.querySelector('h2.title').innerText.trim(); let authorElement = doc.querySelector('a[rel="author"]'); const author = authorElement ? authorElement.innerText.trim() : "匿名"; const contentElement = doc.querySelector('#workskin'); const content = contentElement ? contentElement.innerHTML : "
内容不可用
"; const htmlContent = `