文献小助手(Literature Assistant)

一个油猴脚本,支持提取当前文献页面的标题或DOI并一键跳转到其他网页进行搜索,目前支持网站:Sci Hub、ResearchGate、PubPeer、Google Scholar和Web of Science。

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         文献小助手(Literature Assistant)
// @version      0.0.1
// @author       occasional15
// @homepage     https://github.com/occasional15/Literature-Assistant
// @namespace    https://github.com/occasional15/Literature-Assistant
// @description  一个油猴脚本,支持提取当前文献页面的标题或DOI并一键跳转到其他网页进行搜索,目前支持网站:Sci Hub、ResearchGate、PubPeer、Google Scholar和Web of Science。
// @match        *://*/*
// @license      MIT
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // 样式增强版
    const style = document.createElement('style');
    style.textContent = `
        .qs-container {
            position: fixed;
            bottom: 20px;
            right: 20px;
            z-index: 2147483647;
            font-family: Arial, sans-serif;
        }
        .qs-main-btn {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background: #4285f4;
            color: white;
            border: none;
            cursor: pointer;
            transition: all 0.2s;
        }
        .qs-main-btn:hover {
            transform: scale(1.1);
            box-shadow: 0 3px 12px rgba(66,133,244,0.3);
        }
        .qs-menu {
            display: none;
            position: absolute;
            bottom: 50px;
            right: 0;
            background: white;
            box-shadow: 0 4px 15px rgba(0,0,0,0.15);
            border-radius: 10px;
            min-width: 180px;
            padding: 8px 0;
        }
        .qs-container.active .qs-menu {
            display: block;
            animation: fadeIn 0.2s ease-out;
        }
        .qs-item {
            display: flex;
            align-items: center;
            padding: 12px 16px;
            border: none;
            background: none;
            text-align: left;
            cursor: pointer;
            color: #2c3e50;
            font-size: 14px;
            transition: background 0.2s;
        }
        .qs-item:hover {
            background: #f8f9fa;
        }
        .qs-item::before {
            content: '';
            display: inline-block;
            width: 20px;
            height: 20px;
            margin-right: 12px;
            background-size: contain;
        }
        /* 各平台图标 */
        .qs-item[data-search-engine="scihub"]::before {
            background-image: url('https://sci-hub.se/favicon.ico');
        }
        .qs-item[data-search-engine="scholar"]::before {
            background-image: url('https://scholar.google.com/favicon.ico');
        }
        .qs-item[data-search-engine="researchgate"]::before {
            background-image: url('https://www.researchgate.net/favicon.ico');
        }
        .qs-item[data-search-engine="pubpeer"]::before {
            background-image: url('https://pubpeer.com/favicon.ico');
        }
        .qs-item[data-search-engine="wos"]::before {
            background-image: url('https://www.webofscience.com/favicon.ico');
        }
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
    `;
    document.head.appendChild(style);

    // 创建按钮结构
    const container = document.createElement('div');
    container.className = 'qs-container';
    container.innerHTML = `
        <button class="qs-main-btn">🔍</button>
        <div class="qs-menu">
            <button class="qs-item" data-search-engine="scihub">Sci Hub</button>
            <button class="qs-item" data-search-engine="researchgate">ResearchGate</button>
            <button class="qs-item" data-search-engine="pubpeer">PubPeer</button>
            <button class="qs-item" data-search-engine="scholar">Google Scholar</button>
            <button class="qs-item" data-search-engine="wos">Web of Science</button>
        </div>
    `;
    document.body.appendChild(container);

    // 主按钮交互
    container.querySelector('.qs-main-btn').addEventListener('click', (e) => {
        e.stopPropagation();
        container.classList.toggle('active');
    });

    // 点击页面其他区域关闭
    document.addEventListener('click', () => {
        container.classList.remove('active');
    });

    // 精准标题提取
    function getArticleTitle() {
        const metaTags = [
            'citation_title',
            'og:title',
            'DC.Title',
            'title'
        ].map(name =>
            document.querySelector(`meta[name="${name}"], meta[property="${name}"]`))
        .find(tag => tag);

        if (metaTags?.content) {
            return metaTags.content.replace(/\s*\-\s*.+$/, ''); // 移除网站后缀
        }

        const headings = Array.from(document.querySelectorAll('h1')).find(h1 => {
            const text = h1.textContent.trim();
            return text.length > 10 && !text.includes('404');
        });

        if (headings) {
            return headings.textContent
                .replace(/[\n\r\t]/g, ' ')
                .replace(/\s{2,}/g, ' ')
                .trim();
        }

        return document.title
            .replace(/( - PubMed)?( - ScienceDirect)?( \| SpringerLink)?$/, '')
            .replace(/^[\s\S]{120}[\s\S]*/, m => m.slice(0, 120) + '...');
    }

    // 提取 DOI
    function getArticleDOI() {
        const metaTags = [
            'citation_doi',
            'dc.identifier',
            'dc.identifier.doi'
        ].map(name =>
            document.querySelector(`meta[name="${name}"], meta[property="${name}"]`))
        .find(tag => tag);

        return metaTags ? metaTags.content : null;
    }

    // 智能搜索URL生成器
    const searchEngines = {
        scihub: doi => {
            if (doi) {
                return `https://sci-hub.sidesgame.com/${doi}`;
            }
            return null;
        },
        scholar: title => `https://scholar.google.com/scholar?q=${encodeURIComponent(title)}&hl=en`,
        researchgate: title => `https://www.researchgate.net/search?q=${encodeURIComponent(title)}`,
        pubpeer: title => `https://pubpeer.com/search?q=${encodeURIComponent(title)}&type=publication`,
        wos: title => `https://webofscience.clarivate.cn/wos/alldb/advanced-search`
    };

    // 事件委托处理点击
    document.addEventListener('click', (e) => {
        if (!e.target.classList.contains('qs-item')) return;

        const engine = e.target.dataset.searchEngine;
        const title = getArticleTitle();
        const doi = getArticleDOI();

        // 生成目标URL
        const generator = searchEngines[engine];
        if (!generator) return;
        let targetURL;
        if (engine === 'scihub') {
            targetURL = generator(doi);
            if (!targetURL) {
                console.error('未找到文章的 DOI,无法跳转到 Sci Hub 搜索。');
                return;
            }
        } else {
            targetURL = generator(title);
        }

        window.open(targetURL, '_blank');
    });
})();