// ==UserScript== // @name 导出文献的Bibtex(镜像站) // @namespace jw23 // @version 0.1.1 // @description 支持从知网和谷歌学术镜像导出BiBTex。在知网中,点击论文的checkbox,就会把论文的bibtex复制到剪切板(知网的可能不可用,建议使用谷歌学术) // @author jw23 // @match https://kns.cnki.net/kns8/defaultresult/index // @match https://kns.cnki.net/KXReader/Detai* // @match https://scholar.google.com/scholar* // @match https://scholar.google* // @match https://s.wanfangdata.com.cn/paper* // @match https://*.studiodahu.com* // @match https://usercontent.beijingbang.top* // @match https://*/scholar* // @match https://usercontent.beijingbang.top* // @require https://raw.githubusercontent.com/ORCID/bibtexParseJs/master/bibtexParse.js // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant unsafeWindow // @grant GM_getValue // ==/UserScript== /* ==UserConfig== configure: auth: title: 令牌 description: 请输入petal的令牌 type: text id: title: 组织ID description: 请输入您的组织ID type: text ==/UserConfig== */ let Authorization = GM_getValue("configure.auth", ""); let organization_id = GM_getValue("configure.id", ""); (function () { 'use strict'; document.onkeydown = (e) => { if (e.shiftKey && e.key == "S") { navigator.clipboard .readText() .then((v) => { console.log("正在搜索:", v) window.location.href = `https://scholar.google.com.hk/scholar?hl=zh-CN&as_sdt=0%2C5&q=${v}&btnG=` }) } } const [open, closeDialog] = createLoading() const lauch_in_cnki = () => { setTimeout(() => { waitUnUtil("div.divLoading", () => { console.log("开始插入元素") waitUtil(".cbItem", () => { insertToHTML() }, 3000) }, 8000) }, 1000) } if (document.URL.indexOf("cnki") != -1) { lauch_in_cnki() document.onkeydown = (e) => { if (e.key == "Enter") { lauch_in_cnki() } if (e.ctrlKey && e.shiftKey && e.key == "C") { GM_setClipboard(document.getSelection().toString()) } } document.querySelector("input.search-btn").onclick = () => { lauch_in_cnki() } } else if (document.URL.indexOf("scholar.google") != -1) { waitUtil(".gs_r.gs_or.gs_scl", () => { let items = document.querySelectorAll(".gs_r.gs_or.gs_scl") for (let item of items) { let id = item.querySelector('h3>a').id let box = item.querySelector('div.gs_fl:nth-last-child(1)') let btn = document.createElement('a') btn.style = "cursor:pointer" btn.text = "导出为BiBTex" let btn2 = document.createElement('a') btn2.style = "cursor:pointer" btn2.text = "去知网" btn2.onclick = () => { GM_setClipboard(item.querySelector('h3').textContent) window.open("https://kns.cnki.net/kns8/defaultresult/index"); } btn.onclick = () => { open() getBixTexPageFromGoogle(id).then(page => { let dom = document.createElement("div") dom.innerHTML = page; let lists = dom.querySelector("#gs_citi") let first = lists.querySelector("a").href GM_xmlhttpRequest({ url: first, method: "GET", onload: (response) => { uploadToPetal(response.responseText) closeDialog() GM_setClipboard(response.responseText) }, onerror: () => { closeDialog() } }) }) } box.appendChild(btn) box.appendChild(btn2) } }, 5000) } else if (document.URL.indexOf("wanfangdata") != -1) { waitUtil("div.normal-list", () => { let list = document.querySelectorAll("div.normal-list"); for (let article of list) { let title = article.querySelector("span.title").textContent; let button_group = article.querySelector("div.button-list>div") let btn_google = document.createElement("div") btn_google.className = "wf-list-button" btn_google.textContent = "去Google学术查看" btn_google.onclick = () => { window.open(`https://scholar.google.com.hk/scholar?hl=zh-CN&as_sdt=0%2C5&q=${title}&btnG=`) } button_group.appendChild(btn_google) } }, 8000) } else{ waitUtil(".gs_r.gs_or.gs_scl", () => { let items = document.querySelectorAll(".gs_r.gs_or.gs_scl") for (let item of items) { let id = item.querySelector('h3>a').id let box = item.querySelector('div.gs_fl:nth-last-child(1)') let btn = document.createElement('a') btn.style = "cursor:pointer" btn.text = "导出为BiBTex" let btn2 = document.createElement('a') btn2.style = "cursor:pointer" btn2.text = "去知网" btn2.onclick = () => { GM_setClipboard(item.querySelector('h3').textContent) window.open("https://kns.cnki.net/kns8/defaultresult/index"); } btn.onclick = () => { open() getBixTexPageFromGoogle(id).then(page => { let dom = document.createElement("div") dom.innerHTML = page; let first = dom.querySelector("#gs_citi>a.gs_citi").href GM_xmlhttpRequest({ url: first, method: "GET", onload: (response) => { console.log(response) uploadToPetal(response.responseText) closeDialog() GM_setClipboard(response.responseText) }, onerror: () => { closeDialog() } }) }) } box.appendChild(btn) box.appendChild(btn2) } }, 5000) } setInterval(() => { closeDialog() }, 5000) })(); function createLoading() { let loading = document.createElement("div"); loading.style = `position: fixed; left: 0; right: 0; bottom: 0; top: 0; background: rgb(0 0 0 / 70%); display: flex; justify-content: center; align-items: center; z-index: 9999` loading.id = "jw-loading" loading.className = "jw-hidden" loading.innerHTML = ` ` document.body.appendChild(loading) let dialog = document.querySelector('#jw-loading') return [() => { dialog.className = "" }, () => { dialog.className = "jw-hidden" }] } function insertToHTML() { const [open, closeDialog] = createLoading() let items = document.querySelectorAll('.cbItem') for (let checkbox of items) { checkbox.onchange = (e) => { open() let filename = e.target.value; getBixTex(filename).then(bib => { closeDialog() GM_setClipboard(bib) }).catch(() => { closeDialog() }) } } let box = document.querySelector("#batchOpsBox") let li = document.createElement("li") li.textContent = "导出所有的BibTex" li.onclick = () => { let total = "" for (let checkbox of items) { if (checkbox.checked) { getBixTex(checkbox.value).then(bib => { total += bib; GM_setClipboard(total) }) } } } box.appendChild(li) let lines = document.querySelectorAll("tbody>tr") for (let line of lines) { let icon = document.createElement('td'); icon.textContent = "BibTex" icon.style = "cursor:pointer" let checkbox = line.querySelector('.cbItem') icon.onclick = () => { getBixTex(checkbox.value).then(bib => { uploadToPetal(bib) }) } line.appendChild(icon) } } function getBixTex(filename) { // GM_xmlhttpRequest({ // url: "https://kns.cnki.net/dm/api/ShowExport", // headers: { "Content-Type": "application/x-www-form-urlencoded" }, // data: encodeURIComponent(`FileName=${filename}&DisplayMode=BibTex&OrderParam=0&OrderType=desc&SelectField=&PageIndex=1&PageSize=20&language=&uniplatform=NZKPT&random=${Math.random()}`), // onload: (response) => { // console.log("得到结果:"); // console.log(response.responseText) // }, // onerror: (err) => { // console.log("获取BixTex失败", err) // } // }) return fetch("https://kns.cnki.net/dm/api/ShowExport", { "headers": { "accept": "text/plain, */*; q=0.01", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/x-www-form-urlencoded", "sec-ch-ua": "\"Chromium\";v=\"110\", \"Not A(Brand\";v=\"24\", \"Microsoft Edge\";v=\"110\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"Windows\"", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "x-requested-with": "XMLHttpRequest" }, "referrerPolicy": "strict-origin-when-cross-origin", "body": `FileName=${filename}&DisplayMode=BibTex&OrderParam=0&OrderType=desc&SelectField=&PageIndex=1&PageSize=20&language=&uniplatform=NZKPT&random=0.6662329504606448`, "method": "POST", "mode": "cors", "credentials": "include" }).then(respose => respose.text()).then(result => { let dom = document.createElement("div") dom.innerHTML = result; let bib = dom.querySelector("li") // console.log(bib.textContent) return bib.textContent }) } function waitUtil(ele, callback, timeout) { let success = false; let id = setInterval(function () { let target = document.querySelector(ele) if (target != null) { success = true clearInterval(id); callback(target) } }, 100) setTimeout(() => { if (!success) { clearInterval(id) console.log("[何碧]页面超时") } }, timeout) } function waitUnUtil(ele, callback, timeout) { let success = false; let id = setInterval(function () { let target = document.querySelector(ele) if (target == null) { success = true clearInterval(id); callback(target) } }, 100) setTimeout(() => { if (!success) { clearInterval(id) console.log("[何碧]页面超时") } }, timeout) } function getBixTexPageFromGoogle(id) { return fetch(`/scholar?q=info:${id}:scholar.google.com/&output=cite&scirp=1&hl=zh-CN`, { "headers": { "accept": "*/*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "sec-ch-ua": "\"Chromium\";v=\"110\", \"Not A(Brand\";v=\"24\", \"Microsoft Edge\";v=\"110\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"Windows\"", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "x-requested-with": "XHR" }, "referrerPolicy": "origin-when-cross-origin", "body": null, "method": "GET", "mode": "cors", "credentials": "include" }).then(response => response.text()).then(result => { return result }) } function uploadToPetal(bib) { let bibJSON = bibtexParse.toJSON(bib); let subs = [] for (let i = 0; i < bibJSON.length; i++) { console.log(bibJSON[i]) subs.push({ "meta_json": JSON.stringify({ "title": bibJSON[i].entryTags.title, "author": bibJSON[i].entryTags.author, "journal": bibJSON[i].entryTags.journal, "volume": bibJSON[i].entryTags.volume, "number": bibJSON[i].entryTags.number, "pages": bibJSON[i].entryTags.pages, "year": bibJSON[i].entryTags.year, "entrytype": bibJSON[i].entryType, "citekey": bibJSON[i].citationKey, "editor": "" }) }) } GM_xmlhttpRequest({ url: "https://cite.petal.org/api/organization/7699/document/list", method: "GET", headers: { "Authorization": Authorization, }, onload: (response) => { let lists = JSON.parse(response.response) console.log(lists) for (let item of lists) { if (!bibJSON[0]) { alert("错误,可能需要重新验证") } if (item.meta.citekey == bibJSON[0].citationKey && !item.is_trash) { alert("重复导入相同的引用") return } } GM_xmlhttpRequest({ url: "https://cite.petal.org/api/document/create_stubs", method: "POST", headers: { "Authorization": Authorization, "Content-Type": "application/json" }, data: JSON.stringify({ "organization_id": organization_id, "stubs": subs }), onload: response => { console.log(response.responseText) } }) } }) }