// ==UserScript== // @name 刺猬猫小说下载 // @namespace http://tampermonkey.net/ // @version 1.01 // @description 刺猬猫小说下载,全本下载,单章下载,暂不支持付费章节 // @author backrock12 // @match *://www.ciweimao.com/chapter-list/* // @match *://www.ciweimao.com/chapter/* // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== (function () { 'use strict'; /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ var saveAs = saveAs || function (e) { "use strict"; if (typeof e === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { return } var t = e.document, n = function () { return e.URL || e.webkitURL || e }, r = t.createElementNS("http://www.w3.org/1999/xhtml", "a"), o = "download" in r, a = function (e) { var t = new MouseEvent("click"); e.dispatchEvent(t) }, i = /constructor/i.test(e.HTMLElement) || e.safari, f = /CriOS\/[\d]+/.test(navigator.userAgent), u = function (t) { (e.setImmediate || e.setTimeout)(function () { throw t }, 0) }, s = "application/octet-stream", d = 1e3 * 40, c = function (e) { var t = function () { if (typeof e === "string") { n().revokeObjectURL(e) } else { e.remove() } }; setTimeout(t, d) }, l = function (e, t, n) { t = [].concat(t); var r = t.length; while (r--) { var o = e["on" + t[r]]; if (typeof o === "function") { try { o.call(e, n || e) } catch (a) { u(a) } } } }, p = function (e) { if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)) { return new Blob([String.fromCharCode(65279), e], { type: e.type }) } return e }, v = function (t, u, d) { if (!d) { t = p(t) } var v = this, w = t.type, m = w === s, y, h = function () { l(v, "writestart progress write writeend".split(" ")) }, S = function () { if ((f || m && i) && e.FileReader) { var r = new FileReader; r.onloadend = function () { var t = f ? r.result : r.result.replace(/^data:[^;]*;/, "data:attachment/file;"); var n = e.open(t, "_blank"); if (!n) e.location.href = t; t = undefined; v.readyState = v.DONE; h() }; r.readAsDataURL(t); v.readyState = v.INIT; return } if (!y) { y = n().createObjectURL(t) } if (m) { e.location.href = y } else { var o = e.open(y, "_blank"); if (!o) { e.location.href = y } } v.readyState = v.DONE; h(); c(y) }; v.readyState = v.INIT; if (o) { y = n().createObjectURL(t); setTimeout(function () { r.href = y; r.download = u; a(r); h(); c(y); v.readyState = v.DONE }); return } S() }, w = v.prototype, m = function (e, t, n) { return new v(e, t || e.name || "download", n) }; if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { return function (e, t, n) { t = t || e.name || "download"; if (!n) { e = p(e) } return navigator.msSaveOrOpenBlob(e, t) } } w.abort = function () { }; w.readyState = w.INIT = 0; w.WRITING = 1; w.DONE = 2; w.error = w.onwritestart = w.onprogress = w.onwrite = w.onabort = w.onerror = w.onwriteend = null; return m }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content); if (typeof module !== "undefined" && module.exports) { module.exports.saveAs = saveAs } else if (typeof define !== "undefined" && define !== null && define.amd !== null) { define("FileSaver.js", function () { return saveAs }) } var DivInited = false; var WCContent, WCWords, WCQuit, WCSave, ele; function initDiv() { console.log("initDiv"); if (DivInited) return; DivInited = true; var content = document.createElement("div"); document.body.appendChild(content); content.outerHTML = `
保存
取消
`; WCContent = document.querySelector("#CWDownContent"); WCWords = document.querySelector("#CWDownWords"); WCQuit = document.querySelector("#CWDownQuit"); WCSave = document.querySelector("#CWDownSave"); WCQuit.onclick = function () { WCContent.style.display = "none"; //WCContent.parentNode.removeChild(txtDownContent); }; WCSave.onclick = function () { SaveText(); }; ele = document.createElement('iframe'); ele.name = 'frameid'; ele.id = 'frameid'; ele.width = "195px"; ele.height = "126px"; ele.style.display = 'none'; ele.onload = iframeload; document.body.appendChild(ele); console.log('frame'); } function ShowWords(value) { WCWords.innerHTML = (title ? title + '
' : '') + value; } function findurl() { if (downNum >= downlist.length) return ''; downNum++; if (downlist.length > 0 && downlist[downNum].url) { var url = downlist[downNum].url; return url; } return findurl(); } function iframeload() { if (downlist.length == 0) return; var frame = window.frames[0]; if (frame) { console.log('frame' + downNum); //console.log(frame.document.documentElement); var ftext = frame.document.documentElement.innerHTML; downtext(ftext, downlist[downNum]); iframeloop(); } } function iframeloop() { console.log('iframeloop' + downNum); if (downNum == downlist.length - 1) { SaveText(); } else { if (downlist[downNum].lock) { downlist[downNum].text = '\r\n' + downlist[downNum].title + '\r\n' + '付费章节暂时无法下载'; downNum++; iframeloop(); } else { ele.src = findurl(); } } } var title, info = '' var downlist = []; var downNum = -1; function Analysis() { console.log("Analysis"); downNum = -1; initDiv(); title = document.querySelector(".hd h3").innerText; for (const i of document.querySelectorAll(".hd p")) { info += "\r\n" + i.innerText; } console.log(title); console.log(info); for (const c of document.querySelectorAll(".book-chapter .book-chapter-box")) { var ctitle = c.querySelector('.sub-tit').innerText; downlist.push({ title: ctitle, mk: false, url: '', text: ctitle, complete: true }); for (const a of c.querySelectorAll('.book-chapter-list li a')) { if (a.querySelector('.icon-lock,.icon-unlock')) var lock = true else lock = false; downlist.push({ title: a.innerText, mk: true, url: a.href, text: '', complete: false, lock: lock }); }; }; console.log(downlist); if (downlist.length == 0) { ShowWords(`分析网页失败`); return; } ele.src = findurl(); } function SaveText() { var texts = []; WCContent.style.display = "block"; var ok = 0, error = 0; downlist.forEach(function (c) { if (c.complete) ok++ else error++; texts.push(c.text); }); ShowWords(`已下载完成
共 ${downlist.length} 章节
成功 ${ok} 章节,失败 ${error} 章节 `); var blob = new Blob([title, info, texts.join("\r\n")], { type: "text/plain;charset=utf-8" }); saveAs(blob, `${title}.txt`); } function getElementRootText(element) { let ret = ""; for (const i of element.childNodes) { if (i.nodeType === i.TEXT_NODE) { ret += i.nodeValue; } } return ret.replace(/^\s+|\s+$/g, ""); } /* function image2line(img) { const canvas = document.createElement("canvas"); canvas.width = img.naturalWidth; canvas.height = img.naturalHeight; const ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); return `![${img.alt}](${canvas.toDataURL()} "${img.title}")`; } async function imageUrl2line(url) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => { resolve(image2line(img)); }; img.src = url; }); } */ function downtext(str, obj) { console.log('downtext'); try { if (obj) ShowWords(`共 ${downlist.length} 章节
已下载完成 ${downNum - 1} 章节,剩余 ${downlist.length - downNum} 章节
正在下载 ${downNum}`); var doc = null; doc = document.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = str; let time, num; let lines = []; //console.log(doc); let title = doc.querySelector("#J_BookCnt h3.chapter").firstChild.textContent; for (const i of doc.querySelectorAll("#J_BookCnt p span")) { if (i.textContent.indexOf("更新时间")) { time = i.textContent; } else if (i.textContent.indexOf("字数")) { num = i.textContent; } } lines.push('\r\n\r\n'); lines.push(`# ${title}`); lines.push(` ${time}`); lines.push(` ${num}\r\n`); console.log(title); if ((obj && obj.lock) || doc.querySelectorAll("#J_BookImage").length > 0) { lines.push(`付费章节暂时无法下载`); } else { // 收费章节 for (const i of doc.querySelectorAll("#J_BookImage")) { /* const url = i.style["background-image"].match(/(?:url\(")?(.+)(?:"\))?/)[1]; const line = await imageUrl2line(url); lines.push(line); */ } // 免费章节 for (const i of doc.querySelectorAll("#J_BookRead p:not(.author_say)")) { let line = getElementRootText(i); lines.push(line); /* for (const img of i.querySelectorAll("img")) { lines.push(image2line(img)); } */ } // 作者说 for (const i of doc.querySelectorAll("p.author_say")) { let line = getElementRootText(i); lines.push(` ${line}`); /* for (const img of i.querySelectorAll("img")) { lines.push(image2line(img)); } */ } } var blob = new Blob([lines.join("\r\n")], { type: "text/plain;charset=utf-8" }); if (obj) { obj.text = lines.join("\r\n"); obj.complete = true; } else { saveAs(blob, document.title + ".txt"); } return true; } catch (e) { if (obj) { obj.text = obj.title + " 下载错误!"; obj.complete = true; ShowWords(obj.text); } console.log(e.message); return false; } } function Inited() { var t = document.querySelector(".hd"); if (t) { var e = document.createElement('button'); e.id = 'DownBtn'; e.textContent = '下载'; e.className = 'btn btn-md btn-default' e.onclick = Analysis; t.append(e) console.log('frame'); } var ct = document.querySelector(".read-hd"); if (ct) { var ce = document.createElement('button'); ce.id = 'CDownBtn'; ce.textContent = '单章下载'; ce.className = 'btn btn-md btn-default' ce.onclick = function () { downtext(document.documentElement.innerHTML); }; ct.append(ce) console.log('frame'); } } Inited(); //Analysis(); })();