// ==UserScript== // @name 今日优读 // @description 主要搭建一个知识平台以及读书辅助工具,提供书籍搜索,中图分类和学科搜索。 // @author 018(lyb018@gmail.com) // @contributor Rhilip // @connect * // @grant GM_xmlhttpRequest // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js // @require https://greasyfork.org/scripts/32927-md5-hash/code/MD5%20Hash.js?version=225078 // @include http://uread.today/* // @include http://127.0.0.1:9090/* // @include http://book.ucdrs.superlib.net/views/specific/* // @include http://product.dangdang.com/* // @include https://item.jd.com/* // @include https://book.douban.com/subject/* // @include https://kns.cnki.net/* // @include https://ct.istic.ac.cn/* // @include https://weread.qq.com/* // @include https://yabook.org/* // @include https://yabook.blog/* // @include https://www.jiumodiary.com/* // @include http://www.ncpssd.org/* // @version 0.3.0 // @icon http://uread.today/static/img/favicon.ico // @run-at document-end // @namespace http://uread.today // @downloadURL none // ==/UserScript== // This Userscirpt can't run under Greasemonkey 4.x platform if (typeof GM_xmlhttpRequest === 'undefined') { alert('不支持Greasemonkey 4.x,请换用暴力猴或Tampermonkey') return } ;(function () { 'use strict'; $(document).ready(function () { if (location.href.includes('http://book.ucdrs.superlib.net/views/specific')) { addViewOrEmbody('.tubox dl', '.tutilte'); } else if (location.href.includes('http://product.dangdang.com')) { addViewOrEmbody('#detail_describe', '.name_info h1'); } else if (location.href.includes('https://item.jd.com')) { addViewOrEmbody('.p-parameter-list', '.sku-name'); } else if (location.href.includes('https://book.douban.com/subject')) { addViewOrEmbody('#info', '#wrapper > h1 > span'); } else if (location.href.includes('https://kns.cnki.net/kns8/defaultresult/index')) { handleCNKI(); } else if (location.href.includes('https://ct.istic.ac.cn/site/organize/word')) { handleIstic(); } else if (location.href.includes('https://weread.qq.com/')) { handleWeread(); } else if (location.href.includes('https://yabook.')) { handleYabook(); } else if (location.href.includes('https://www.jiumodiary.com/')) { handleJiumodiary(); } else if (location.href.includes('http://www.ncpssd.org/index.aspx')) { handleNcpssd(); } else if (location.href.includes('http://uread.today/')) { handleuRead(); } else if (location.href.includes('http://127.0.0.1:9090/')) { handleuRead(); } }) function addViewOrEmbody(isbnselecter, titleselecter) { let match = document.querySelector(isbnselecter).innerText.match(/ISBN.*/) if (match) { let isbn = match[0].replace(/\D/g, ''); doGet('http://api.uread.today/master/anon/book/get?isbn=' + isbn, {isbn: isbn}, function(ret, responseDetail, meta) { if (ret && ret.resultcode === 1) { $(titleselecter).append(''); } else { $(titleselecter).append(''); } }, function(err, meta) { console.warn(err) }); } } function similar(s, t) { if (!s || !t) { return 0 } var l = s.length > t.length ? s.length : t.length var n = s.length var m = t.length var d = [] var min = function(a, b, c) { return a < b ? (a < c ? a : c) : (b < c ? b : c) } var i, j, si, tj, cost if (n === 0) return m if (m === 0) return n for (i = 0; i <= n; i++) { d[i] = [] d[i][0] = i } for (j = 0; j <= m; j++) { d[0][j] = j } for (i = 1; i <= n; i++) { si = s.charAt(i - 1) for (j = 1; j <= m; j++) { tj = t.charAt(j - 1) if (si === tj) { cost = 0 } else { cost = 1 } d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost) } } let res = (1 - d[n][m] / l) return res } function handleuRead() { // 试读 $('#tags').parent().after('试读: ...') var a = $('#superlibnet'); if (a) { loadSrcDoc (a.attr('href'), {}, function (doc, responseDetail, meta) { var element = Object.values(doc.scripts).find(element => element.textContent.includes('send_requestajax')) if (element) { var pattern = /".*?"/ if (pattern.test(element.textContent)) { var url = pattern.exec(element.textContent)[0].replaceAll('"', ''); doText ('http://book.ucdrs.superlib.net/' + url, {}, function (responseText, responseDetail, meta) { var htmlText = unescape(responseText.trim()); var html = (new DOMParser()).parseFromString(htmlText, 'text/html'); var as = ''; for(var a of html.querySelectorAll('.link a')) { if (as.length > 0) { as += ' | ' } if (a.textContent === '图书馆文献传递') { as += '' + a.textContent + '' } else { as += '' + a.textContent + '' } } $('#tryread').html(as) }, function (responseDetail, meta) { $('#tryread').html('
') }) } } }, function (responseDetail, meta) { $('#tryread').html('
发生异常,请刷新重试。
') }) } else { $('#tryread').html('
') } // 电子书 let title = $('#title').text(); let srctitle = $('#title > span:nth-child(1)').text(); let isbn = $('#isbn').text(); $('#ebook').parent().after('其他: Z-Library(...)' + ' | Library Genesis(...)' + ' | 微信读书(...)' + ' | 互助联盟(...)' + ' | LoreFree(...)' + ' | 雅书搜索' + '') // Z-Library loadDoc('https://1lib.us/s/' + isbn, {title: title, isbn: isbn}, function(doc, responseDetail, meta) { let found = false; for (let a of doc.querySelectorAll('table.resItemTable h3[itemprop=name] a')) { //if (a.textContent.includes(meta.title) || meta.title.includes(a.textContent)) { if (similar(a.textContent, meta.title) > 0.5) { let url = a.href.replace(location.host, 'b-ok.global').replace('http:', 'https:'); found = true; loadDoc(url, {}, function(doc, responseDetail, meta) { let addDownloadedBook = doc.querySelector('.addDownloadedBook'); if (addDownloadedBook) { let txt = addDownloadedBook.textContent.match(/\(.*\)/g); url = addDownloadedBook.href.replace(location.host, 'b-ok.global').replace('http:', 'https:'); if ($('#ZLibrary').text().includes('(...)')) { $('#ZLibrary').html(' Z-Library' + txt + ''); } else { $('#ZLibrary').append(' Z-Library' + txt + ''); } } else { $('#ZLibrary').html(' Z-Library(暂无资源)'); } }, function(err, meta) { $('#ZLibrary').html(' Z-Library(暂无资源)'); }); } } if (!found) { $('#ZLibrary').html(' Z-Library(暂无资源)'); } }, function(err, meta) { $('#ZLibrary').html(' Z-Library(暂无资源)'); }); // Library Genesis loadDoc('https://libgen.rs/search.php?req=' + isbn + '&lg_topic=libgen&open=0&view=simple&res=25&phrase=1&column=identifier', {title: title, isbn: isbn}, function(doc, responseDetail, meta) { let tr = doc.querySelector('body > table.c > tbody > tr:nth-child(2)'); if (tr) { let size = tr.querySelector('td:nth-child(8)').textContent; let extension = tr.querySelector('td:nth-child(9)').textContent; let download = tr.querySelector('td:nth-child(10) a'); $('#libgen').html(' Library Genesis(' + extension + ', ' + size + ')'); } else { $('#libgen').html(' Library Genesis(暂无资源)'); } }, function(err, meta) { $('#libgen').html(' Library Genesis(暂无资源)'); }); // 微信读书 doGet('https://weread.qq.com/web/search/global?keyword=' + title + '&maxIdx=0&fragmentSize=120&count=40', {title: title, isbn: isbn}, function(json, responseDetail, meta) { if (json.books && json.books.length > 0) { let bookId let paring = function (val) { return val.replace(/(/g, '') .replace(/)/g, '') .replace(/【|﹝|〔/g, '') .replace(/】|﹞|〕/g, '') .replace(/ *编|著|译|等|校/g, '') .replace(/翻译/g, '') .replace(/\(审校\)/g, '') .replace(/译校/g, '') .replace(/编译/g, '') .replace(/正校/g, '') .replace(/•|・|▪/g, '') .replace(/\] +/g, '') .replace(/ *· */g, '') .replace(/ /g, '') .replace(/./g, '') .replace(/\. */g, '.') } let createId = function (bookId) { let str = MD5(bookId, false) let strSub = str.substr(0, 3) let func = function (id) { if (/^\d*$/.test(id)) { for (var len = id['length'], c = [], a = 0; a < len; a += 9) { var b = id['slice'](a, Math.min(a + 9, len)) c['push'](parseInt(b)['toString'](16)) } return ['3', c] } for (var d = '', i = 0; i < id['length']; i++) { d += id['charCodeAt'](i)['toString'](16) } return ['4', [d]] } let fa = func(bookId) strSub += fa[0], strSub += 2 + str['substr'](str['length'] - 2, 2) for (var m = fa[1], j = 0; j < m.length; j++) { var n = m[j].length.toString(16) 1 === n['length'] && (n = '0' + n), strSub += n, strSub += m[j], j < m['length'] - 1 && (strSub += 'g') } return strSub.length < 20 && (strSub += str.substr(0, 20 - strSub.length)), strSub += MD5(strSub, false).substr(0, 3) } for (let index = 0; index < json.books.length; index++) { const book = json.books[index] var creators = document.querySelectorAll('#author a') if (creators) { for (const creator of creators) { let author = paring(book.bookInfo.author) let lastName = paring(creator.textContent || '') if (lastName && (lastName.startsWith(author) || lastName.endsWith(author) || author.startsWith(lastName) || author.endsWith(lastName))) { bookId = book.bookInfo.bookId break } } } if (bookId) { break } } if (bookId) { let urlid = createId(bookId) let url = `https://weread.qq.com/web/reader/${urlid}` $('#weread').html(' 微信读书'); } else { $('#weread').html(' 微信读书(暂无资源)'); } } else { $('#weread').html(' 微信读书(暂无资源)'); } }, function(err, meta) { $('#weread').html('互助联盟(暂无资源)'); }); // 互助联盟 loadDoc('https://www.readersteam.com/vip/?aff=readersteam&q=' + isbn, {title: title, isbn: isbn}, function(doc, responseDetail, meta) { let a = doc.querySelector('dl.result-list > dt:nth-child(1) a'); if (a) { $('#readersteam').html('互助联盟(发起互助)'); } else { $('#readersteam').html('互助联盟(暂无资源)'); } }, function(err, meta) { $('#readersteam').html('互助联盟(暂无资源)'); }); // LoreFree let lorefreeurl = 'https://ebook2.lorefree.com/site/index?s=' + srctitle loadDoc(lorefreeurl, {title: title, isbn: isbn}, function(doc, responseDetail, meta) { let divs = doc.querySelectorAll('div.body-content > div:nth-child(2) div'); if (divs && divs.length > 0) { $('#LoreFree').html(' LoreFree(' + divs.length + '+)'); } else { $('#LoreFree').html(' LoreFree(暂无资源)'); } }, function(err, meta) { $('#LoreFree').html(' LoreFree(暂无资源)'); }); } function handleCNKI() { let q = getQuery(location.search) if (q) { $('#txt_search').val(decodeURIComponent(q)) $('.search-btn').click() } } function handleIstic() { let q = getQuery(location.search) if (q) { $('#termname').val(decodeURIComponent(q)) $('#btn-search').click() } } function handleWeread() { let q = getQuery(location.search) if (q) { setTimeout(() => { $('.search_input_text').val(decodeURIComponent(q)) $('.search_input_right').click() }, 2000) } } function handleYabook() { let q = getQuery(location.search) if (q) { $('#bdcsMain').val(decodeURIComponent(q)) $('.btn').click() } } function handleJiumodiary() { let q = getQuery(location.search) if (q) { $('#SearchWord').val(decodeURIComponent(q)) $('#SearchButton').click() } } function handleNcpssd() { let q = getQuery(location.search) if (q) { $('#text_search').val(decodeURIComponent(q)) $('#but_search').click() } } function getQuery(url) { if (!url) return false; var q = url.match(/[?&]q=([^&#]*)/i); if (!q || !q[1]) return false; return q[1]; } // 判断,空返回空字符串 function opt(val) { if (!val) return ''; if (val instanceof Array) { if (val.length > 0) { return val[0]; } } else { return val; } } // 对使用GM_xmlhttpRequest返回的html文本进行处理并返回DOM树 function page_parser(responseText, src) { // 替换一些信息防止图片和页面脚本的加载,同时可能加快页面解析速度 if (!src) { responseText = responseText.replace(/s+src=/ig, ' data-src='); // 图片,部分外源脚本 responseText = responseText.replace(/]*?>[\S\s]*?<\/script>/ig, ''); //页面脚本 } return (new DOMParser()).parseFromString(responseText, 'text/html'); } // 加载网页 function loadDoc (url, meta, callback, fail) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (responseDetail) { if (responseDetail.status === 200) { let doc = page_parser(responseDetail.responseText, false) callback(doc, responseDetail, meta) } else if (fail){ fail(responseDetail, meta); } }, onerror: function(err) { if (fail) { fail(err, meta); } } }) } // 加载网页 function loadSrcDoc (url, meta, callback, fail) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (responseDetail) { if (responseDetail.status === 200) { let doc = page_parser(responseDetail.responseText, true) callback(doc, responseDetail, meta) } else if (fail){ fail(responseDetail, meta); } }, onerror: function(err) { if (fail) { fail(err, meta); } } }) } // get请求 function doText (url, meta, callback, fail) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (responseDetail) { if (responseDetail.status === 200) { callback(responseDetail.responseText, responseDetail, meta) } else if (fail){ fail(responseDetail, meta); } }, onerror: function(err) { if (fail) { fail(err, meta); } } }) } // get请求 function doGet (url, meta, callback, fail) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (responseDetail) { if (responseDetail.status === 200) { callback(JSON.parse(responseDetail.responseText), responseDetail, meta) } else if (fail){ fail(responseDetail, meta); } }, onerror: function(err) { if (fail) { fail(err, meta); } } }) } // post请求 function doPost (url, headers, data, meta, callback, fail) { GM_xmlhttpRequest({ method: "POST", url: url, data: data, headers: headers, onload: function(responseDetail){ if (responseDetail.status === 200) { callback(JSON.parse(responseDetail.responseText), responseDetail, meta) } else if (fail){ fail(responseDetail, meta); } }, onerror: function(err) { if (fail) { fail(err, meta); } } }) } })()