X (Twitter) Feed Text Extractor

Extract and monitor formatted text content from X (Twitter) feed

// ==UserScript==
// @name         X (Twitter) Feed Text Extractor
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  Extract and monitor formatted text content from X (Twitter) feed
// @match        https://x.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let isMonitoring = false;
    let collectedTweets = new Set();
    let observer;

    const button = document.createElement('button');
    button.textContent = '开始监控X内容';
    button.style.position = 'fixed';
    button.style.top = '10px';
    button.style.right = '10px';
    button.style.zIndex = '9999';
    document.body.appendChild(button);

    button.addEventListener('click', toggleMonitoring);

    function formatRelativeTime(dateStr) {
        const now = new Date();
        const past = new Date(dateStr);
        const diffMs = now - past;
        const diffSec = Math.floor(diffMs / 1000);
        const diffMin = Math.floor(diffSec / 60);
        const diffHour = Math.floor(diffMin / 60);
        const diffDay = Math.floor(diffHour / 24);
        const diffMonth = Math.floor(diffDay / 30);
        const diffYear = Math.floor(diffDay / 365);

        if (diffYear > 0) {
            return `${diffYear}年前`;
        } else if (diffMonth > 0) {
            return `${diffMonth}个月前`;
        } else if (diffDay > 0) {
            return `${diffDay}天前`;
        } else if (diffHour > 0) {
            return `${diffHour}小时前`;
        } else if (diffMin > 0) {
            return `${diffMin}分钟前`;
        } else {
            return '刚刚';
        }
    }

    function toggleMonitoring() {
        if (isMonitoring) {
            stopMonitoring();
            displayCollectedTweets();
        } else {
            startMonitoring();
        }
    }

    function startMonitoring() {
        isMonitoring = true;
        button.textContent = '停止监控并显示内容';
        collectedTweets.clear();

        const currentTweets = document.querySelectorAll('[data-testid="tweet"]');
        currentTweets.forEach(processTweet);

        const config = { childList: true, subtree: true };
        observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            const tweets = node.querySelectorAll('[data-testid="tweet"]');
                            tweets.forEach(processTweet);
                        }
                    });
                }
            });
        });

        observer.observe(document.body, config);
    }

    function stopMonitoring() {
        isMonitoring = false;
        button.textContent = '开始监控X内容';
        if (observer) {
            observer.disconnect();
        }
    }

    function processTweet(tweet) {
        const tweetContent = formatTweet(tweet);
        if (tweetContent) {
            collectedTweets.add(tweetContent);
        }
    }

    function displayCollectedTweets() {
        let extractedText = Array.from(collectedTweets).join('\n\n---\n\n');
        const newWindow = window.open('', '_blank');
        newWindow.document.write('<pre>' + extractedText + '</pre>');
    }

    function formatTweet(tweet) {
        const authorElement = tweet.querySelector('div[data-testid="User-Name"]');
        if (!authorElement) return null;

        const authorName = authorElement.querySelector('span')?.textContent || 'Unknown';
        const authorId = authorElement.querySelector('a[href^="/"]')?.getAttribute('href')?.slice(1) || 'Unknown';
        const timeElement = tweet.querySelector('time');
        const tweetTime = timeElement ? formatRelativeTime(timeElement.getAttribute('datetime')) : 'Unknown time';

        let formattedTweet = `作者: ${authorName} (@${authorId})\n发布时间: ${tweetTime}\n\n`;

        const tweetTextElement = tweet.querySelector('[data-testid="tweetText"]');
        if (tweetTextElement) {
            formattedTweet += `内容: ${tweetTextElement.textContent}\n`;
        }

        const retweetElement = tweet.querySelector('[data-testid="socialContext"]');
        if (retweetElement) {
            const retweetAuthor = retweetElement.textContent.replace('转推', '').trim();
            formattedTweet = `转推自: ${retweetAuthor}\n\n${formattedTweet}`;
        }

        return formattedTweet;
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址