Metrics Extractor for Xiaohongshu Note Manager

展示指标数据(浏览量、评论数、点赞数、收藏数、转发数)(聪明豆专属)。

当前为 2024-12-13 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Metrics Extractor for Xiaohongshu Note Manager
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  展示指标数据(浏览量、评论数、点赞数、收藏数、转发数)(聪明豆专属)。
// @author       DUZ
// @match        https://creator.xiaohongshu.com/new/note-manager*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 防止脚本多次运行
    if (document.getElementById('metrics-extractor-container')) {
        console.log('Metrics Extractor 已经运行,退出脚本。');
        return;
    }

    const metrics = ['浏览量', '评论数', '点赞数', '收藏数', '转发数'];
    let categorizedData = [];
    let totals = {
        '浏览量': 0,
        '评论数': 0,
        '点赞数': 0,
        '收藏数': 0,
        '转发数': 0
    };

    function extractMetrics() {
        console.log('开始提取指标数据...');
        const iconDivs = document.querySelectorAll('div.icon');
        console.log('找到的div.icon数量:', iconDivs.length);
        const numbers = [];

        iconDivs.forEach(div => {
            const span = div.querySelector('span');
            if (span) {
                const numberText = span.textContent.trim();
                // 移除非数字字符(如逗号)
                const cleanedNumber = numberText.replace(/[^\d]/g, '');
                const number = parseInt(cleanedNumber, 10);
                if (!isNaN(number)) {
                    numbers.push(number);
                } else {
                    console.warn(`无法解析数字: "${numberText}"`);
                }
            }
        });

        console.log('提取到的数字:', numbers);

        if (numbers.length % 5 !== 0) {
            console.warn('提取的数字数量不是5的倍数,可能存在数据缺失或多余。');
        }

        categorizedData = [];
        for (let i = 0; i < numbers.length; i += 5) {
            const item = {};
            metrics.forEach((metric, index) => {
                if (i + index < numbers.length) {
                    item[metric] = numbers[i + index];
                } else {
                    item[metric] = null;
                }
            });
            categorizedData.push(item);
        }

        console.log('分类后的数据:', categorizedData);

        // 计算总数
        totals = {
            '浏览量': 0,
            '评论数': 0,
            '点赞数': 0,
            '收藏数': 0,
            '转发数': 0
        };
        categorizedData.forEach(item => {
            metrics.forEach(metric => {
                const value = item[metric];
                if (typeof value === 'number') {
                    totals[metric] += value;
                }
            });
        });

        console.log('各指标总数:', totals);

        // 如果面板已存在,则更新数据
        if (document.getElementById('metrics-extractor-container')) {
            updateMetricsPanel();
        } else {
            createMetricsPanel();
        }
    }

    function createMetricsPanel() {
        console.log('创建指标面板...');
        // 创建样式
        const style = document.createElement('style');
        style.innerHTML = `
        #metrics-extractor-container {
            position: fixed;
            top: 20px;
            right: 20px;
            width: 320px;
            background: rgba(255, 255, 255, 0.95);
            border: 1px solid #ccc;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            padding: 15px;
            z-index: 10000;
            font-family: Arial, sans-serif;
            max-height: 90vh;
            overflow-y: auto;
        }
        #metrics-extractor-container h2 {
            text-align: center;
            margin-top: 0;
            font-size: 18px;
        }
        #metrics-extractor-container table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 15px;
        }
        #metrics-extractor-container th, #metrics-extractor-container td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: center;
            font-size: 14px;
        }
        #metrics-extractor-container th {
            background-color: #f2f2f2;
        }
        #metrics-extractor-container button {
            width: 100%;
            padding: 10px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            margin-bottom: 10px;
        }
        #metrics-extractor-container button:hover {
            background-color: #45a049;
        }
        #metrics-extractor-details {
            display: none;
            max-height: 300px;
            overflow-y: auto;
        }
        `;
        document.head.appendChild(style);

        // 创建容器
        const container = document.createElement('div');
        container.id = 'metrics-extractor-container';

        // 创建标题
        const title = document.createElement('h2');
        title.textContent = '指标总数';
        container.appendChild(title);

        // 创建总数表格
        const totalsTable = document.createElement('table');
        const totalsThead = document.createElement('thead');
        const totalsHeaderRow = document.createElement('tr');
        const metricHeader = document.createElement('th');
        metricHeader.textContent = '指标';
        const totalHeader = document.createElement('th');
        totalHeader.textContent = '总数';
        totalsHeaderRow.appendChild(metricHeader);
        totalsHeaderRow.appendChild(totalHeader);
        totalsThead.appendChild(totalsHeaderRow);
        totalsTable.appendChild(totalsThead);

        const totalsTbody = document.createElement('tbody');
        for (const [metric, total] of Object.entries(totals)) {
            const row = document.createElement('tr');
            const metricCell = document.createElement('td');
            metricCell.textContent = metric;
            const totalCell = document.createElement('td');
            totalCell.textContent = total;
            row.appendChild(metricCell);
            row.appendChild(totalCell);
            totalsTbody.appendChild(row);
        }
        totalsTable.appendChild(totalsTbody);
        container.appendChild(totalsTable);

        // 创建按钮
        const toggleButton = document.createElement('button');
        toggleButton.id = 'metrics-extractor-toggle';
        toggleButton.textContent = '显示详细数据';
        container.appendChild(toggleButton);

        // 创建详细数据部分
        const detailsSection = document.createElement('div');
        detailsSection.id = 'metrics-extractor-details';

        const detailsTitle = document.createElement('h2');
        detailsTitle.textContent = '详细数据';
        detailsSection.appendChild(detailsTitle);

        const detailsTable = document.createElement('table');
        const detailsThead = document.createElement('thead');
        const detailsHeaderRow = document.createElement('tr');
        const projectHeader = document.createElement('th');
        projectHeader.textContent = '项目';
        detailsHeaderRow.appendChild(projectHeader);
        metrics.forEach(metric => {
            const th = document.createElement('th');
            th.textContent = metric;
            detailsHeaderRow.appendChild(th);
        });
        detailsThead.appendChild(detailsHeaderRow);
        detailsTable.appendChild(detailsThead);

        const detailsTbody = document.createElement('tbody');
        categorizedData.forEach((item, index) => {
            const row = document.createElement('tr');
            const projectCell = document.createElement('td');
            projectCell.textContent = index + 1;
            row.appendChild(projectCell);
            metrics.forEach(metric => {
                const cell = document.createElement('td');
                cell.textContent = item[metric] !== null ? item[metric] : '-';
                row.appendChild(cell);
            });
            detailsTbody.appendChild(row);
        });
        detailsTable.appendChild(detailsTbody);
        detailsSection.appendChild(detailsTable);

        container.appendChild(detailsSection);
        document.body.appendChild(container);

        // 添加按钮点击事件
        toggleButton.addEventListener('click', () => {
            if (detailsSection.style.display === 'none' || detailsSection.style.display === '') {
                detailsSection.style.display = 'block';
                toggleButton.textContent = '隐藏详细数据';
            } else {
                detailsSection.style.display = 'none';
                toggleButton.textContent = '显示详细数据';
            }
        });

        console.log('指标面板已创建。');
    }

    function updateMetricsPanel() {
        console.log('更新指标面板数据...');
        const totalsTableBody = document.querySelector('#metrics-extractor-container table tbody');
        const detailsTableBody = document.querySelector('#metrics-extractor-details table tbody');

        // 更新总数表格
        totalsTableBody.innerHTML = '';
        for (const [metric, total] of Object.entries(totals)) {
            const row = document.createElement('tr');
            const metricCell = document.createElement('td');
            metricCell.textContent = metric;
            const totalCell = document.createElement('td');
            totalCell.textContent = total;
            row.appendChild(metricCell);
            row.appendChild(totalCell);
            totalsTableBody.appendChild(row);
        }

        // 更新详细数据表格
        detailsTableBody.innerHTML = '';
        categorizedData.forEach((item, index) => {
            const row = document.createElement('tr');
            const projectCell = document.createElement('td');
            projectCell.textContent = index + 1;
            row.appendChild(projectCell);
            metrics.forEach(metric => {
                const cell = document.createElement('td');
                cell.textContent = item[metric] !== null ? item[metric] : '-';
                row.appendChild(cell);
            });
            detailsTableBody.appendChild(row);
        });

        console.log('指标面板数据已更新。');
    }

    // 初始提取和显示
    extractMetrics();

    // 监听DOM变化以处理动态加载内容
    const observer = new MutationObserver((mutations) => {
        extractMetrics();
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();