// ==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.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();
})();