您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show journal name, ISSN, SJR ranking and H-Index using ISSN search only
当前为
// ==UserScript== // @name SCImago Journal Rank for Google Scholar // @namespace https://greasyfork.org/ // @version 1.1 // @description Show journal name, ISSN, SJR ranking and H-Index using ISSN search only // @author Bui Quoc Dung // @match https://scholar.google.com/* // @grant GM_xmlhttpRequest // @connect api.crossref.org // @connect www.scimagojr.com // @require https://code.jquery.com/jquery-3.6.0.min.js // ==/UserScript== (function () { 'use strict'; const CROSSREF_API = 'https://api.crossref.org/works'; const SJR_SEARCH_URL = 'https://www.scimagojr.com/journalsearch.php?q='; const SJR_BASE_URL = 'https://www.scimagojr.com/'; function queryCrossRef(title, callback) { const url = `${CROSSREF_API}?query.title=${encodeURIComponent(title)}&rows=1`; GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (res) { try { const data = JSON.parse(res.responseText); const item = data.message.items?.[0]; if (!item) return callback(null); const journal = item['container-title']?.[0] || null; const issn = item.ISSN?.[0] || null; callback({ journal, issn }); } catch (e) { callback(null); } }, onerror: () => callback(null) }); } function querySJRByISSN(issn, callback) { if (!issn) { callback("❌ No ISSN available"); return; } const searchUrl = `${SJR_SEARCH_URL}${encodeURIComponent(issn)}`; GM_xmlhttpRequest({ method: 'GET', url: searchUrl, onload: function (res) { const doc = new DOMParser().parseFromString(res.responseText, "text/html"); const firstLink = doc.querySelector('.search_results a'); if (!firstLink) { callback("❌ ISSN not found on SJR"); return; } const href = firstLink.getAttribute('href'); if (!href) { callback("❌ Unable to get journal detail link"); return; } const journalUrl = SJR_BASE_URL + href; GM_xmlhttpRequest({ method: 'GET', url: journalUrl, onload: function (res2) { const doc2 = new DOMParser().parseFromString(res2.responseText, "text/html"); const container = doc2.querySelector('div.journalgrid'); if (!container) { callback("⚠️ No SJR data found"); return; } const sjrPs = container.querySelectorAll('p.hindexnumber'); let sjrValue = null; let quartile = null; let hIndex = null; if (sjrPs.length >= 2) { sjrValue = sjrPs[0].childNodes[0]?.textContent.trim(); quartile = sjrPs[0].querySelector('span')?.textContent.trim(); hIndex = sjrPs[1].textContent.trim(); } let result = ''; if (sjrValue && quartile) { result += `SJR ${quartile}; ${sjrValue}`; } else if (sjrValue) { result += `SJR ${sjrValue}`; } else { result += `⚠️ SJR not found`; } if (hIndex) { result += ` | H-Index: ${hIndex}`; } callback(result); }, onerror: () => callback("❌ Error accessing journal page") }); }, onerror: () => callback("❌ Error querying SJR") }); } function processEntry(entry) { if (entry.querySelector('.sjr-crossref-info')) return; const title = entry.querySelector('.gs_rt')?.textContent.trim(); if (!title) return; const infoDiv = document.createElement('div'); infoDiv.className = 'sjr-crossref-info'; infoDiv.textContent = '⏳ Looking up...'; entry.appendChild(infoDiv); queryCrossRef(title, result => { if (!result || !result.issn) { infoDiv.textContent = '❌ ISSN not found (CrossRef)'; return; } const { journal, issn } = result; infoDiv.textContent = `📖 ${journal} (ISSN: ${issn}) — Fetching SJR...`; querySJRByISSN(issn, sjrInfo => { infoDiv.textContent = `📖 ${journal} (ISSN: ${issn}) — ${sjrInfo}`; }); }); } const observer = new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (!(node instanceof HTMLElement)) continue; const entries = node.matches('.gs_ri') ? [node] : node.querySelectorAll?.('.gs_ri') || []; entries.forEach(entry => processEntry(entry)); } } }); observer.observe(document.body, { childList: true, subtree: true }); // Initial run document.querySelectorAll('.gs_ri').forEach(entry => processEntry(entry)); })();