SCImago Journal Rank for Google Scholar

Show journal name, ISSN, SJR ranking and H-Index using ISSN search only

当前为 2025-05-23 提交的版本,查看 最新版本

// ==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));
})();