Greasy Fork

Greasy Fork is available in English.

全国图书馆参考咨询联盟

下载DPF少操作一步,「文章下载」替换成「PDF下载」,点击直接下载。也可辅助Zotero translator的Superlib.js,直接抓取PDF。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           全国图书馆参考咨询联盟
// @description    下载DPF少操作一步,「文章下载」替换成「PDF下载」,点击直接下载。也可辅助Zotero translator的Superlib.js,直接抓取PDF。
// @author         018([email protected])
// @contributor    Rhilip
// @connect        *
// @grant          GM_xmlhttpRequest
// @grant          GM_setClipboard
// @grant          GM_addStyle
// @grant          GM_setValue
// @grant          GM_getValue
// @grant          GM_listValues
// @grant          GM_deleteValue
// @grant          GM_registerMenuCommand
// @require        https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @require        http://greasyfork.icu/scripts/368137-encodeToGb2312/code/encodeToGb2312.js?version=601683
// @include        http://jour.ucdrs.superlib.net/*
// @include        http://book.ucdrs.superlib.net/views/specific/*
// @version        0.2.1
// @run-at         document-end
// @namespace      http://018.ai
// ==/UserScript==

// This Userscirpt can't run under Greasemonkey 4.x platform
if (typeof GM_xmlhttpRequest === 'undefined') {
    alert('不支持Greasemonkey 4.x,请换用暴力猴或Tampermonkey')
    return
}

// 不属于的页面
if (!/ucdrs.superlib.net/.test(location.host)) {
    return
}

;(function () {
    'use strict';

    $(document).ready(function () {
        if (location.href.includes('book.ucdrs.superlib.net/views/specific')) {
            $('#libinfo .title').after($('<div class="box"><h3 class="boxHd">下载 </h3><div class="link" id="download"><span style="color:#989B9B">(...)</span></div> <div class="link" id="downloadTry"><span style="color:#989B9B">(...)</span></div></div>'));
            // 中图分类
            for(let dd of $('.tubox dl dd')) {
                if (dd.textContent.startsWith('【中图法分类号】')) {
                    let clcs = opt(opt(/【中图法分类号】.*/.exec(dd.textContent)).match(/[a-zA-Z0-9\.;]+/)).split(';');
                    var ddTextContent = dd.textContent;
                    for(let clc of clcs) {
                        ddTextContent = ddTextContent.replace(clc, '<a id="clc" target="_blank" href="http://uread.today/clc?c=' + clc + '">' + clc + '</a>') + ' <span id="clcText_' + clc.replace('.', '') + '">(...)</span>\n';
                        requestClc(clc, function(subject) {
                            appendsubject(subject, dd);
                        }, dd);
                    }
                    $(dd).html(ddTextContent)
                } else if (dd.textContent.startsWith('【ISBN号】')) {
                    let title = $('.tutilte').text();
                    let isbn = opt(/【ISBN号】.*/.exec(dd.textContent)).replace(/【ISBN号】|-|\n/g, '');

                    let intervalID = setInterval(function() {
                        requestBOK(title, isbn);
                        clearInterval(intervalID);
                    }, 1000);
                }
            }

            var as1 = $('.testimg a');
            if (as1.length == 0) {
                as1 = $('.link a');
            }
            if (as1.length > 0) {
                loadBookHref(as1.get(0));
            }
        } else if (location.href.includes('jour.ucdrs.superlib.net/views/specific')) {
            // 论文,文章下载
            setTimeout(function(){
                var as0 = $('.link a');
                if (as0.length > 0) {
                    loadJourHref(as0.get(0));
                }
            }, 1000);
        } else if (location.href.includes('jour.ucdrs.superlib.net/searchJour')) {
            // 文章下载
            for (var a of $('.book1 .get a')) {
                if (a.textContent != '文章下载') continue;

                loadJourHref(a);
            }
        }
    })

    // 加载试读页面
    function loadBookHref(a) {
        loadDoc(a.href, {a: a}, function(doc, responseDetail, meta) {
            let $assistUrl = $(doc.querySelector('#downpdf [name=assistUrl]'));
            let assistUrl = $assistUrl.attr('value');
            let $cntUrl = $(doc.querySelector('#downpdf [name=cntUrl]'));
            let cntUrl = $cntUrl.attr('value');

            $('#downloadTry').html('<a target="_blank" href="' + cntUrl + '">下载正文试读</a> <a target="_blank" href="' + assistUrl + '">下载目录页</a>');
        });
    }

    // 加载PDF页面
    function loadJourHref(a) {
        loadDoc(a.href, {a: a}, function(doc, responseDetail, meta) {
            var download = doc.querySelector('.download .down_bnt');
            if (download) {
                $(meta.a).attr('href', download.href);
                $(meta.a).html('PDF下载');
            }
        });
    }

    // 请求电子书
    function requestBOK(title, isbn) {
        loadDoc('https://b-ok.global/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)) {
                    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 ($('#download').text() == '(...)') {
                                $('#download').html('<a target="_blank" href="' + url + '">下载' + txt + '</a>');
                            } else {
                                $('#download').append('<a target="_blank" href="' + url + '">下载' + txt + '</a>');
                            }
                        } else {
                            $('#download').html('<span style="color:#989B9B"> 暂无资源 </span>');
                        }
                    }, function(err, meta) {
                        $('#download').html('<span style="color:#989B9B"> 暂无资源 </span>');
                    });
                }
            }

            if (!found) {
                $('#download').html('<span style="color:#989B9B"> 暂无资源 </span>');
            }
        }, function(err, meta) {
            $('#download').html('<span style="color:#989B9B"> 暂无资源 </span>');
        });
    }

    // 请求istic,获取分类名称,备用,暂不启用。
    function requestClc(clc, subject, dd) {
        doGet('http://api.uread.today/master/anon/ch_lib_cls/info?code=' + clc, {dd: dd, clc: clc}, function(json, responseDetail, meta) {
            if (json.resultcode == 40000 && meta.clc.length > 0) {
                if (meta.clc.includes('.')) {
                    requestClc(meta.clc.replace(/\.\d*$/, ''), subject, meta.dd);
                } else {
                    requestClc(meta.clc.replace(/\d$/, ''), subject, meta.dd);
                }
                return;
            }

            let clcs = [];
            clcs.push(...json.data.clc.parents.map((e) => e.clc + ' ' + hanldeClcText(e.name)));
            clcs.push(json.data.clc.clc + ' ' + hanldeClcText(json.data.clc.name))
            htmlclc(clc, clcs, meta.dd);

            subject(json.data.subject)
        }, function(err, meta) {
            requestClcA(meta.clc, meta.dd);
        });
    }

    // 请求istic,获取分类名称,备用,暂不启用。
    function requestClcA(clc, dd) {
        doPost('https://ct.istic.ac.cn/site/clc/getByClassName?t=' + new Date().getTime(),
               { "Content-Type": "application/x-www-form-urlencoded" }, 'classname=' + clc, {dd: dd, clc: clc}, function(json, responseDetail, meta) {
            if (json.length == 0 && meta.clc.length > 0) {
                if (meta.clc.includes('.')) {
                    requestClcA(meta.clc.replace(/\.\d*$/, ''), meta.dd);
                } else {
                    requestClcA(meta.clc.replace(/\d$/, ''), meta.dd);
                }
                return;
            }

            let clcs = [];
            let jsonMap = {};
            let pid;

            let level;
            for (let i = 0; i < json.length; i ++) {
                if (clcs.length == 0 && json[i].classNum.split('/').includes(clc)) {
                    clcs.push(json[i].classNum + ' ' + hanldeClcText(json[i].className, meta.dd));

                    pid = json[i].pid;
                    level = json[i].level;
                } else if( json[i].level < level) {
                    jsonMap[json[i].id + ''] = json[i];
                }
            }

            clcText(meta.clc, pid, jsonMap, clcs, meta.dd);

            htmlclc(meta.clc, clcs, meta.dd);
        }, function(err, meta) {
            requestClcB(meta.clc, meta.dd);
        });
    }

    //  处理clc文字
    function clcText(clc, pid, jsonMap, rets, dd) {
        if (!jsonMap || !rets) return;

        if( jsonMap[pid] ) {
            rets.unshift(jsonMap[pid].classNum + ' ' + hanldeClcText(jsonMap[pid].className, dd));

            if (jsonMap[pid].level <= 2) return;

            clcText(clc, jsonMap[pid].pid, jsonMap, rets, dd);
        }
    }

    function htmlclc(clc, rets, dd) {
        if (rets.length > 0) {
            let clcText = $('#clcText_' + clc.replace('.', ''));
            if (clcText.text() == '(...)' ) {
                clcText.html('(' + rets.join('<span style="color:#989B9B"> ▸ </span>') + ')');
            }
        } else {
            let clcText = $('#clcText_' + clc.replace('.', ''));
            if (clcText.text() == '(...)' ) {
                clcText.html('<span style="color:#989B9B">(查无此信息)</span>');
            }
        }
    }

    function hanldeClcText(txt, dd) {
        var splits = txt.split(/、|(|)|\(|\)/);
        var retss = [];
        for (var s of splits) {
            if (s.length == 0) continue;

            retss.push(' <a target="_blank" href="http://uread.today/clc-subject?t=content&q=' + s + '">' + s + '</a>');

            //requestxhma(s, dd);
        }
        return retss.join('、');
    }

    // 请求clcindex,获取分类名称
    function requestClcB(clc, dd) {
        var url = 'https://www.clcindex.com/category/' + clc;
        loadDoc(url, {dd: dd, clc: clc, url: url}, function(doc, responseDetail, meta) {
            let clcs = [];
            for (let li of doc.querySelectorAll('.breadcrumb li.active')) {
                if (!li) continue;

                var txtContent = li.textContent.trim();
                var clcCode;
                var index = txtContent.indexOf(' ');
                if (index > 0) {
                    clcCode = txtContent.substr(0, index);
                    txtContent = txtContent.substr(index + 1);
                }

                clcs.push(clcCode + ' ' + hanldeClcText(txtContent, meta.dd));
            }

            $('#clc').attr('href', meta.url);
            htmlclc(clcs);
        }, function(err, meta) {
            if (err.status == 404) {
                if (meta.clc.includes('.')) {
                    requestClcB(meta.clc.replace(/\.\d*$/, ''), meta.dd);
                } else {
                    requestClcB(meta.clc.replace(/\d$/, ''), meta.dd);
                }
                return;
            }

            let clcText = $('#clcText_' + meta.clc);
            if (clcText.text() == '(...)' ) {
                clcText.html('<span style="color:#989B9B">(无法获取)</span>');
            }
        });

    }

    // 请求xhma,获取学科
    function requestxhma(s, dd) {
        var url = 'http://xkfl.xhma.com/search?w=' + s;
        loadDoc(url, {dd: dd}, function(doc, responseDetail, meta) {
            let spans = doc.querySelectorAll('.data li:not(.t) span');//code
            if (spans.length == 1) {
                let name = spans[0].nextElementSibling.textContent.trim();
                if (name.includes(s)) {
                    let code = spans[0].textContent.trim();
                    appendsubject(' <a target="_blank" href="' + spans[0].nextElementSibling.href + '">' + code + ' ' + name + '</a>', meta.dd);
                }
            } else if (spans.length > 1) {
                for (let span of spans) {
                    if (!span) continue;

                    let name = span.nextElementSibling.textContent.trim();
                    if (name != s && (name != s + '学')) continue;

                    let code = span.textContent.trim();

                    appendsubject('<a target="_blank" href="' + span.nextElementSibling.href + '">' + code + ' ' + name + '</a>', meta.dd);
                }
            }
        }, function(err, meta) {
        });
    }

    function appendsubject(subject, dd) {
        let clcText = $('#subjectText');
        let subjectText = ' <a target="_blank" href="http://uread.today/subject?c=' + subject.code + '">' + subject.code + ' ' + subject.name + '</a>'
        if (clcText.length == 0) {
            $(dd).after($(' \n<dd >【学科分类号】<span id="subjectText"><span id="subject" style="display: none;">' + subject.code + '</span><span>' + subjectText + '</span></span></dd>'));
        } else {
            clcText.append('<span style="color:#989B9B"> | </span><span>' + subjectText + '</span>');
        }
    }

    // 判断,空返回空字符串
    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) {
        // 替换一些信息防止图片和页面脚本的加载,同时可能加快页面解析速度
        responseText = responseText.replace(/s+src=/ig, ' data-src='); // 图片,部分外源脚本
        responseText = responseText.replace(/<script[^>]*?>[\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)
                    callback(doc, 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);
                }
            }
        })
    }
})()

// 测试URL
// http://jour.ucdrs.superlib.net/searchJour?sw=%E6%85%A2%E6%80%A7&allsw=%23%2Call%E9%95%BF%E6%97%B6&bCon=&ecode=utf-8&channel=searchJour&Field=all