// ==UserScript==
// @name 刺猬猫小说下载
// @namespace http://tampermonkey.net/
// @version 1.10
// @description 刺猬猫小说下载,全本下载,单章下载,暂不支持付费章节
// @author backrock12
// @match *://www.ciweimao.com/chapter-list/*
// @match *://www.ciweimao.com/chapter/*
// @match *://www.ciweimao.com/book/*
// @require https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js
// @require https://cdn.jsdelivr.net/npm/file-saver@1.3.8/FileSaver.min.js
// @grant GM_xmlhttpRequest
// @downloadURL none
// ==/UserScript==
(function () {
'use strict';
var DivInited = false, IsCancel = false;
var WCContent, WCWords, WCQuit, WCSave, WCContinue;
var title, info = '';
var desc, grade, update, titleinfo = '';
var downlist = [];
var vol = 1;
var num = 0;
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");
WCContinue = document.querySelector("#CWCContinue");
WCQuit.onclick = function () {
IsCancel = true;
DivInited = false;
WCContent.style.display = "none";
WCWords.innerHTML = '';
WCContent.parentNode.removeChild(WCContent);
};
WCContinue.onclick = function () {
if (downlist.length == 0) {
Analysis();
}
else {
continueDown();
}
};
WCSave.onclick = function () {
SaveText();
};
}
function ShowWords(value) {
WCWords.innerHTML = (title ? title + '
' : '') + value;
}
class Book {
constructor(name, url, text, title_mk, lock, complete, status, iframeId) {
this.name = name;
this.url = url;
this.text = text;
this.title_mk = title_mk;
this.lock = lock;
this.complete = complete || false;
this.status = status || 'Null';
this.iframeId = iframeId
this.num = num++
}
setstatus(status, text) {
this.complete = true;
this.status = status;
if (text)
this.text = text;
}
setiframeId(iframeId) {
this.complete = false;
this.status = 'Down';
this.iframeId = iframeId;
}
setnull() {
this.complete = false;
this.status = 'Null';
this.iframeId = '';
}
isDown() {
return this.status == 'Down';
}
isEnd() {
// return this.title_mk == false && this.complete && (this.iframeId || this.iframeId != '');
return this.title_mk == false && this.complete;
}
isCan() {
// return this.title_mk == false && this.complete == false && (!this.iframeId || this.iframeId == '');
return this.title_mk == false && this.complete == false;
}
}
function* cratebookmap(items) {
for (let i of items) {
if (i.isCan()) {
yield i;
}
}
}
async function loopDown() {
console.log('loopDown');
let bookobj = cratebookmap(downlist);
let result = bookobj.next();
while (!result.done && !IsCancel) {
if (bookobj)
ShowWords(`共 ${downlist.length} 章节
已下载完成 ${result.value.num - 1} 章节,剩余 ${downlist.length - result.value.num} 章节
正在下载 ${result.value.num}`);
await IframeInit(result.value);
IframeClear(result.value);
result = bookobj.next();
}
if (result.done)
SaveText();
}
function continueDown() {
console.log('continueDown');
IsCancel = true;
downlist.forEach((item) => {
if (item.isDown()) {
IframeClear(item);
item.setnull();
}
});
IsCancel = false;
loopDown();
}
function IframeClear(bookobj) {
console.log('IframeClear' + bookobj.iframeId);
var ele = document.getElementById(bookobj.iframeId);
try {
ele.src = 'about:blank';
ele.onload = null;
ele.contentWindow.document.write('');
ele.contentWindow.document.clear();
ele.contentWindow.close();
ele.parentNode.removeChild(ele);
ele = null;
} catch (e) {
console.log('IframeClear' + e.message);
}
bookobj.iframeId = '';
}
async function IframeInit(bookobj) {
return new Promise((resolve, reject) => {
console.log('IframeInit');
console.log(bookobj);
var iframeId = 'iframe_' + vol + '_' + bookobj.num;
var ele1 = document.createElement('iframe');
ele1.src = bookobj.url + '#Autodown';
ele1.name = iframeId;
ele1.id = iframeId;
ele1.width = "195px";
ele1.height = "126px";
ele1.style.display = 'none';
ele1.onload = function () {
var frame = this;//document.getElementById(iframeId);
if (frame) {
resolve(downtext(frame.contentDocument, bookobj));
}
}
document.body.appendChild(ele1);
bookobj.setiframeId(iframeId);
});
}
async function getRequest() {
return new Promise(function (resolve, reject) {
GM_xmlhttpRequest({
method: 'GET',
url: 'https://www.ciweimao.com/book/100114521',
onload: function (result) {
resolve(result.response);
}
});
});
}
async function getdesc() {
var str = await getRequest()
var doc = null;
try {
doc = document.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = str;
}
catch (e) {
console.log('parse error');
}
desc = doc.querySelector(".book-desc").innerText;
grade = doc.querySelector(".book-grade").innerText;
update = doc.querySelector(".update-time").innerText;
var a= document.querySelector(".book-info .title");
console.log(a);
for (const i of document.querySelector(".book-info .title")) {
titleinfo += "\r\n" + i.innerText;
console.log(titleinfo);
}
}
function Analysis() {
console.log("Analysis");
IsCancel = false;
title = '';
info = '';
initDiv();
if (WCContent) {
WCContent.style.display = "block";
ShowWords(`分析网页中`);
}
getdesc();
title = document.querySelector(".hd h3").innerText;
for (const i of document.querySelectorAll(".hd p")) {
info += "\r\n" + i.innerText;
}
console.log(title);
for (const c of document.querySelectorAll(".book-chapter .book-chapter-box")) {
var ctitle = c.querySelector('.sub-tit').innerText;
downlist.push(
new Book(ctitle, '', ctitle, true, false, true, 'OK')
);
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(
new Book(a.innerText, a.href, '', false, lock)
);
};
};
console.log(downlist);
if (downlist.length == 0) {
ShowWords(`分析网页失败`);
return;
}
loopDown();
}
function SaveText() {
var texts = [];
WCContent.style.display = "block";
var ok = 0, error = 0;
downlist.forEach(function (c) {
if (c.isEnd())
ok++
else if (c.title_mk && c.complete)
error++;
texts.push(c.text);
});
ShowWords(`已下载完成
共 ${downlist.length} 章节
成功 ${ok} 章节,失败 ${error} 章节 `);
var blob = new Blob([titleinfo, "\r\n" + grade, "\r\n" +update, desc.trim(), 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) {
var dataURL = GM_xmlhttpRequest({
method: 'GET',
url: img.src,
responseType: "blob",
onload: function (result) {
var reader = new window.FileReader();
reader.readAsDataURL(result.response);
reader.onloadend = function () {
return reader.result;
}
}
});
return ``;
return;
img.crossOrigin = 'Anonymous'
html2canvas(img, {
allowTaint: true,
logging: false,
useCORS: true,
}
).then(function (canvas) {
var dataUrl = canvas.toDataURL();
console.log(dataUrl);
console.log(canvas);
var im = document.createElement("img");
im.src = dataUrl;
document.body.append(canvas);
});
return;
img.crossOrigin = "Anonymous";
var canvas = document.createElement("canvas");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
console.log('img4');
var dataURL = canvas.toDataURL("image/" + ext);
console.log('img5');
console.log(dataURL);
return ``;
}
async function image2lineasync(img) {
return new Promise((resolve, reject) => {
resolve(image2line(img));
});
}
async function imageUrl2line(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve(image2line(img));
};
img.src = url;
console.log(url);
});
}
async function downtext(str, bookobj) {
if (bookobj && bookobj.lock) {
bookobj.setstatus('OK', '\r\n' + bookobj.name + '\r\n' + '付费章节暂时无法下载');
return;
}
console.log('downtext' + str);
try {
var doc = str;
let time, num;
let lines = [];
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`);
if ((bookobj && bookobj.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")) {
const line = await image2lineasync(img);
lines.push(line);
} */
}
// 作者说
for (const i of doc.querySelectorAll("p.author_say")) {
let line = getElementRootText(i);
lines.push(` ${line}`);
/* for (const img of i.querySelectorAll("img")) {
const line = await image2lineasync(img);
lines.push(line);
} */
}
}
var blob = new Blob([lines.join("\r\n")], { type: "text/plain;charset=utf-8" });
if (bookobj) {
bookobj.setstatus('OK', lines.join("\r\n"));
} else {
IsCancel = false;
saveAs(blob, title + ".txt");
}
return true;
}
catch (e) {
if (bookobj) {
bookobj.setstatus('ERROR ', bookobj.name + " 下载错误!");
ShowWords(bookobj.text);
}
console.log('downtext ERROR ' + e.message);
return false;
}
}
function Inited() {
getdesc();
if (location.hash && location.hash == '#Autodown') {
} else {
if (location.hash && location.hash == '#Autoclick') {
var autoclick = true;
}
console.log('Inited');
let reg = new RegExp('www.ciweimao.com/book/*');
if (reg.test(location.href)) {
var b = document.querySelector(".btn-group");
if (b) {
let id = location.href.substr(location.href.lastIndexOf('/') + 1);
let e = document.createElement('a');
e.id = 'BDownBtn';
e.textContent = '全本下载';
e.className = 'btn btn-lg btn-danger'
e.target = '_blank'
e.href = `https://www.ciweimao.com/chapter-list/${id}/book_detail#Autoclick`;
b.append(e);
}
}
let t = document.querySelector(".hd");
if (t) {
let e = document.createElement('button');
e.id = 'TDownBtn';
e.textContent = '下载';
e.className = 'btn btn-md btn-default'
e.onclick = Analysis;
t.append(e);
if (autoclick)
Analysis();
}
let ct = document.querySelector(".read-hd");
if (ct) {
let ce = document.createElement('button');
ce.id = 'CDownBtn';
ce.textContent = '单章下载';
ce.className = 'btn btn-md btn-default'
ce.onclick = function () { downtext(document); };
ct.append(ce);
}
}
}
Inited();
//Analysis();
})();