网页文本词频分析 (使用 innerText)

使用 innerText 分析网页文本词频,显示在可拖拽悬浮窗口

// ==UserScript==
// @name         网页文本词频分析 (使用 innerText)
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  使用 innerText 分析网页文本词频,显示在可拖拽悬浮窗口
// @match        *://*/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';
    function countMostFrequentTwoWords(text) {
        if (typeof text !== 'string' || text.length < 2) {
            return "输入文本不合法或长度不足"; // 处理无效输入
        }

        // 1. 清理文本:移除标点符号和多余空格
        text = text.replace(/[,、;:。?!“”‘’《》【】{}()…—·!¥…&……%@*]/g, ''); // 移除中文标点
        text = text.replace(/\s+/g, ' '); // 将多个空格替换为一个空格
        text = text.trim(); // 去除首尾空格

        // 2. 分割成单字数组
        let characters = text.split('');

        // 3. 创建双字词并计数
        let twoWordCounts = {};
        for (let i = 0; i < characters.length - 1; i++) {
            let twoWord = characters[i] + characters[i + 1];
            twoWordCounts[twoWord] = (twoWordCounts[twoWord] || 0) + 1;
        }

        // 4. 找到出现次数最多的两个双字词
        let sortedTwoWords = Object.entries(twoWordCounts).sort(([, countA], [, countB]) => countB - countA);

        //处理没有双字词的情况
        if (sortedTwoWords.length === 0) {
            return "文本中没有双字词";
        }

        // 返回出现次数最多的两个双字词
        let topTwo = sortedTwoWords.slice(0, 2);
        let result = "";
        for(let i = 0; i < topTwo.length; i++){
            result += `第${i+1}名: "${topTwo[i][0]}" 出现了 ${topTwo[i][1]} 次\n`;
        }
        return result;
    }



    function wordFrequency(text) {
        if (typeof text !== 'string' || text.length === 0) {
            return {};
        }

        // 预处理:去除标点符号和空格,转换为小写
        text = text.replace(/[\p{P}\s]+/gu, '').toLowerCase();

        const frequency = {};
        const n = text.length;

        for (let i = 0; i < n; i++) {
            for (let j = 1; j <= 4 && i + j <= n; j++) { // 限制词组最多四个字
            const word = text.substring(i, i + j);
            frequency[word] = (frequency[word] || 0) + 1;
            }
        }

        // 将词频对象转换为数组并按词频降序排序 (可选)
        const sortedFrequency = Object.entries(frequency).sort(([, a], [, b]) => b - a);

            // 如果需要返回对象而不是数组,可以省略上面的排序代码,直接返回 frequency 对象

        return sortedFrequency; // 或者 return frequency;
    }

    function topWordFrequency(text, topN = 20) {
        if (typeof text !== 'string' || text.length === 0) {
            return []; // 或者返回空对象 {},取决于你的需求
        }

        // 预处理:去除标点符号和空格,转换为小写
        text = text.replace(/[\p{P}\s]+/gu, '').toLowerCase();

        const frequency = {};
        const n = text.length;

        for (let i = 0; i < n; i++) {
            for (let j = 1; j <= 4 && i + j <= n; j++) {
                const word = text.substring(i, i + j);
                frequency[word] = (frequency[word] || 0) + 1;
            }
        }

        // 将词频对象转换为数组并按词频降序排序
        const sortedFrequency = Object.entries(frequency).sort(([, a], [, b]) => b - a);

        // 返回前 topN 个词组
        return sortedFrequency.slice(0, topN);
    }

    function analyzeText() {
        // 使用 innerText 获取所有文本
        let allText = document.body.innerText;
        let output=topWordFrequency(allText)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // 清理文本
        //allText = allText.replace(/[,。??.,\/#!$%\^&\*;:{}=\-_`~()]/g,"").replace(/\s{2,}/g," ").toLowerCase();
        // 定义需要切割的标点符号,注意转义特殊字符
        //let punctuation = /[,、;:。?!“”‘’《》【】{}()]/g;

        //let words = allText.split(punctuation);

        // 过滤掉空字符串
        //words = words.filter(word => word.trim() !== "");

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//         let words= countMostFrequentTwoWords(allText)
//         // 统计词频
//         let wordFrequency = {};
//         for (let word of words) {
//             if (word !== "") {
//                 wordFrequency[word] = (wordFrequency[word] || 0) + 1;
//             }
//         }

//         // 排序词频
//         let sortedWords = Object.entries(wordFrequency).sort(([, a], [, b]) => b - a);

        // 创建显示结果的 div
        let resultDiv = document.createElement("div");
        resultDiv.id = "wordFrequencyResult"; // 添加 id 方便后续操作
        resultDiv.style.position = "fixed";
        resultDiv.style.top = "10px";
        resultDiv.style.left = "10px";
        resultDiv.style.backgroundColor = "white";
        resultDiv.style.border = "1px solid black";
        resultDiv.style.padding = "10px";
        resultDiv.style.zIndex = "9999";
        resultDiv.style.maxHeight = "500px";
        resultDiv.style.overflowY = "scroll";
        resultDiv.style.resize = "both"; // 允许调整大小
        resultDiv.style.overflow = "auto";
        resultDiv.style.minWidth = "200px"; // 设置最小宽度,防止拖拽成一条线

        // let output = "词频分析结果:\n";
        // for (let [word, frequency] of sortedWords) {
        //     output += word + ": " + frequency + "\n";
        // }
        resultDiv.textContent = output;

        document.body.appendChild(resultDiv);

        // 使 div 可拖拽
        dragElement(resultDiv);
    }

    //拖拽功能
    function dragElement(elmnt) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        if (elmnt.querySelector(".drag-header")) {
            /* 如果存在 header,则 header 是拖拽的“手柄” */
            elmnt.querySelector(".drag-header").onmousedown = dragMouseDown;
        } else {
            /* 否则,整个元素都是拖拽的“手柄” */
            elmnt.onmousedown = dragMouseDown;
        }

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            // 获取鼠标在光标位置的初始位置
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            // 计算新的光标位置
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            // 设置元素的新位置
            elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
            elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
        }

        function closeDragElement() {
            /* 停止移动 */
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }


    // 创建分析按钮
    let analyzeButton = document.createElement("button");
    analyzeButton.textContent = "分析词频";
    analyzeButton.style.position = "fixed";
    analyzeButton.style.top = "10px";
    analyzeButton.style.right = "10px";
    analyzeButton.style.zIndex = "9999";
    analyzeButton.onclick = analyzeText;
    document.body.appendChild(analyzeButton);
})();