知网PDF下载助手

直接以PDF格式下载知网上的文献, 包括期刊论文和博硕士论文

As of 2020-12-20. See the latest version.

// ==UserScript==
// @id             CNKI_PDF_Supernova
// @name           知网PDF下载助手
// @version        3.1.2
// @namespace      https://github.com/supernovaZhangJiaXing/Tampermonkey/
// @author         Supernova
// @description    直接以PDF格式下载知网上的文献, 包括期刊论文和博硕士论文
// @include        http*://*.cnki.net/*
// @include        http*://*.cnki.net.*/*
// @include        */DefaultResult/Index*
// @include        */KNS8/AdvSearch*
// @include        */detail.aspx*
// @include        */CatalogViewPage.aspx*
// @include        */Article/*
// @include        */kns/brief/*
// @include        */kns55/brief/*
// @include        */grid2008/brief/*
// @include        */detail/detail.aspx*
// @exclude        http://image.cnki.net/*
// @require        https://unpkg.com/pdf-lib@1.13.0/dist/pdf-lib.js
// @require        https://cdn.jsdelivr.net/gh/tabedit/code-segment@f730e9d9573c4ca7e758766e6a8fb282faae38af/outline.esm.js
// @run-at         document-idle
// @grant          unsafeWindow
// @grant          GM_setClipboard
// @grant          GM_xmlhttpRequest
// ==/UserScript==

'use strict';
var $ = unsafeWindow.jQuery;
var contents = '';
var pdf;

$(document).ready(function() {
    var myurl = window.location.href;
    var isDetailPage = myurl.indexOf("detail.aspx") != -1 ? true: false; // 点进文献后的详情页
    var isContentPage = myurl.indexOf("kdoc/download.aspx?") != -1 ? true : false; // 分章下载

    if (isDetailPage === false) {
        if (window.location.href.indexOf("kns8") != -1){ // 文献检索页面, 防止在别处出现
            $(document).ajaxSuccess(function() {
                if (arguments[2].url.indexOf('/Brief/GetGridTableHtml') + 1) {
                    // 防止标志-链接不匹配, 统一默认转换为PDF
                    $('.downloadlink').attr('href', toPDF);
                    convert_box.innerText = "当前默认下载格式: PDF (点击转换)";
                    // TODO: 调整一下图标样式为黄色那个下载箭头, 插入原下载按钮后面
//                     var pdf_a = document.createElement("a");
//                     pdf_a.className = "downloadlink icon-download"
//                     var pdf_i = document.getElementsByClassName("downloadlink icon-download")[0];
//                     pdf_i.parentElement.insertBefore(pdf_a, i.nextElementSibling);
//                     pdf_a.innerHTML = "<i></i>";
//                     pdf_a.style = "background-position: -200px -20px";
                }
            });
            var convert_box = document.createElement("div");
            convert_box.innerText = "当前默认下载格式: PDF (点击转换)";
            convert_box.className = "ecp_tn-tab";
            convert_box.style = "color: blue; font-weight: bolder";
            convert_box.onclick = function() {
                if (convert_box.innerText == "当前默认下载格式: PDF (点击转换)") {
                    convert_box.innerText = "当前默认下载格式: CAJ (点击转换)";
                    $('.downloadlink').attr('href', toCAJ);
                } else if (convert_box.innerText == "当前默认下载格式: CAJ (点击转换)") {
                    convert_box.innerText = "当前默认下载格式: PDF (点击转换)";
                    $('.downloadlink').attr('href', toPDF);
                }
            };
            var mycnki = $('#icnki');
            mycnki.parent()[0].insertBefore(convert_box, mycnki.nextElementSibling);
        }
    }
    // 如果进了详情页, 博硕士论文下面会出现五个个按钮: 手机, 整本, 分页, 分章, 在线
    // 期刊论文下会有三个按钮
    else {
        // 只对"博硕论文"详情页做优化, 否则影响期刊页面的显示
        // 新版界面更改了详情页的显示方式, 原本的"博硕论文"四个大字没有了, 只能数按钮数量了
        var operate_buttons = document.getElementsByClassName("operate-btn")[0];
        if (operate_buttons.childNodes[3].innerText == "整本下载") {
            // 整本下载替换为CAJ下载
            var dlcaj = document.getElementsByClassName("btn-dlcaj")[0];
            dlcaj.innerHTML = dlcaj.innerHTML.replace("整本", "CAJ");

            // 添加PDF下载
            var dlpdf = document.getElementsByClassName("btn-dlpdf")[0]; // 从分页下载获取链接
            var pdfdown = dlpdf.getElementsByTagName('a');
            var dl = pdfdown[0].href.replace("&dflag=downpage", "&dflag=pdfdown");
            var dlpdfli = document.createElement('li');
            dlpdfli.className = "btn-dlpdf";
            var a = document.createElement('a');
            a.innerHTML = "<i></i>PDF 下载";
            a.target="_blank";
            a.id = "pdfDown";
            a.name = "pdfDown";
            a.href = dl;
            dlpdfli.appendChild(a);
            operate_buttons.appendChild(dlpdfli);
            operate_buttons.insertBefore(dlpdfli, dlcaj.nextElementSibling);

            // 从分章下载获取目录的URL
            var dlChapter = document.getElementsByClassName("btn-dlcaj")[1];
            var dlChapter_link = dlChapter.childNodes[0];

            // 分页下载替换为目录复制
            dlpdf.innerHTML = dlpdf.innerHTML.replace("分页下载", "目录复制");
            dlpdf.className = "btn-dlcaj";
            pdfdown[0].removeAttribute("href");
            pdfdown[0].removeAttribute("target");
            pdfdown[0].removeAttribute("onclick");
            pdfdown[0].id = "copyContents";
            pdfdown[0].name = "copyContents";
            pdfdown[0].removeChild(pdfdown[0].childNodes[0]);
            dlpdf.onclick = function() {
                // 1. 获取目录url
                var url = dlChapter_link.href || '?';
                url = 'https://chn.oversea.cnki.net/kcms/download.aspx' + url.replace(/%20/g, '').match(/\?.*/)[0];
                // 2. 使用GM_xmlhttpRequest获取目录内容
                // 3. 在copycontents函数复制目录
                GM_xmlhttpRequest({method: 'GET', url: url, onload: copycontents});
            };

            // 添加目录下载
            var dlContent = document.createElement('li');
            dlContent.className = "btn-dlpdf";
            var dlContent_link = document.createElement('a');
            dlContent_link.innerHTML = "目录下载";
            dlContent_link.id = "content";
            dlContent_link.name = "content";
            dlContent.appendChild(dlContent_link);
            dlContent.onclick = function (){
                // 1. 获取目录url
                var url = dlChapter_link.href || '?';
                url = 'https://chn.oversea.cnki.net/kcms/download.aspx' + url.replace(/%20/g, '').match(/\?.*/)[0];
                // 2. 使用GM_xmlhttpRequest获取目录内容
                // 3. 在done函数使用Blob下载目录
                GM_xmlhttpRequest({method: 'GET', url: url, onload: downloadcontents});
            };
            operate_buttons.insertBefore(dlContent, dlChapter);

            // 右侧添加使用教程
            var how_to_use_li = document.createElement('li');
            how_to_use_li.className = "btn-phone";
            var how_to_use = document.createElement('a');
            how_to_use.innerHTML = "脚本说明";
            how_to_use.target="_blank";
            how_to_use.id = "how_to_use";
            how_to_use.name = "how_to_use";
            how_to_use.href = 'https://mp.weixin.qq.com/s?__biz=MzU5MTY4NDUzMg==&mid=2247484384&idx=1&sn=6a135e824793d26b5bd8884b78c1f751&chksm=fe2a753bc95dfc2d3a5f6383553fc369894c5021619c85bb7554583bdcb8c10624bf2a7097e1&token=462651491&lang=zh_CN#rd';
            how_to_use_li.appendChild(how_to_use);
            operate_buttons.appendChild(how_to_use_li);

            // 右侧添加工具下载(PdgContentEditor)
            var pce_li = document.createElement('li');
            pce_li.className = "btn-phone";
            var pce = document.createElement('a');
            pce.innerHTML = "目录工具下载";
            pce.target="_blank";
            pce.id = "pce_down";
            pce.name = "pce_down";
            pce.href = 'https://pan.baidu.com/s/12i-uv3xALmHOjKpnO691aw';
            pce_li.appendChild(pce);
            operate_buttons.appendChild(pce_li);
        }
    }
});

function toCAJ() {
    return $(this).data('CAJ', this.href.replace(/&dflag=\w*|$/, '&dflag=nhdown')).data("CAJ");
}

function toPDF() {
    return $(this).data('PDF', this.href.replace(/&dflag=\w*|$/, '&dflag=pdfdown')).data("PDF");
}

function get_content(cnt_list){
    // 要写的内容
    var contents = "";
    for (var i = 0; i < cnt_list.length - 1; i++) { // 长度减一, 因为最后一个是text
        var cnt_item = cnt_list[i].childNodes[1].childNodes[1];
        cnt_item = cnt_item.innerHTML;
        var cnt_page = cnt_list[i].childNodes[3].childNodes[0].textContent.trim().split("-")[0]; // 知网的目录给的是个范围, 正常只需要前半部分
        contents = contents + cnt_item.trim().replace(/&nbsp;/g, " ") + "\t" + cnt_page + "\r\n";
    }
    return contents;
}

function fuckcontent(xhr) {
    // 目录列表
    var cnt_list = $('tr', xhr.responseText);
    // 要写的内容
    contents = get_content(cnt_list);
}

function do_download_content(contents, title){
    var data = new Blob([contents],{type:"text/plain; charset=UTF-8"});
    var downloadUrl = window.URL.createObjectURL(data);
    var anchor = document.createElement("a");
    anchor.href = downloadUrl;
    anchor.download = "目录索引_" + title.innerHTML.trim().replace(/&nbsp;/g, "");
    anchor.click();
    window.URL.revokeObjectURL(data);
    window.alert("目录索引已保存, 请使用PdgCntEditor软件将目录整合到PDF中");
}

function copycontents(xhr){
    fuckcontent(xhr); // 目录赋值给了全局变量contents
    // 运用油猴脚本自带的复制
    GM_setClipboard(contents);
    window.alert('目录已复制到剪贴板');
};

function downloadcontents(xhr){
    fuckcontent(xhr); // 目录赋值给了全局变量contents
    var title = document.getElementsByClassName("wx-tit")[0].childNodes[1];
    do_download_content(contents, title)
};