X 推文关键词逐条搜索滚动器(增强版)

一条一条匹配推文关键词,找到后将其定位在页面顶部,支持停止按钮,暗黑界面优化,美观浮窗,滚动速度可调

目前为 2025-03-30 提交的版本。查看 最新版本

// ==UserScript==
// @name         X 推文关键词逐条搜索滚动器(增强版)
// @namespace    http://tampermonkey.net/
// @version      2.3
// @description  一条一条匹配推文关键词,找到后将其定位在页面顶部,支持停止按钮,暗黑界面优化,美观浮窗,滚动速度可调
// @author       _Sure.Lee
// @match        https://x.com/*
// @match        https://twitter.com/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let stopRequested = false;
    let processedTweets = new Set();
    let currentSearchKeyword = '';
    let scrollStep = 1000; // 默认滚动像素
    let searchStatus = '准备就绪';
    let matchCount = 0;
    let totalProcessed = 0;

    function createSearchUI() {
        const container = document.createElement('div');
        container.id = 'custom-search-ui';
        container.style.position = 'fixed';
        container.style.top = '10px';
        container.style.left = '10px';
        container.style.zIndex = '9999';
        container.style.backgroundColor = '#1e1e1e';
        container.style.color = '#f5f5f5';
        container.style.border = '1px solid #444';
        container.style.padding = '10px';
        container.style.borderRadius = '10px';
        container.style.boxShadow = '0 4px 12px rgba(0,0,0,0.6)';
        container.style.fontSize = '14px';
        container.style.display = 'flex';
        container.style.flexDirection = 'column';
        container.style.gap = '8px';
        container.style.minWidth = '300px';
        container.style.transition = 'height 0.3s ease';

        let isCollapsed = false;

        const header = document.createElement('div');
        header.style.display = 'flex';
        header.style.justifyContent = 'space-between';
        header.style.alignItems = 'center';
        header.style.cursor = 'move';

        const title = document.createElement('div');
        title.textContent = 'X 推文搜索';
        title.style.fontWeight = 'bold';
        title.style.color = '#ff9632';

        const collapseBtn = document.createElement('button');
        collapseBtn.textContent = '—';
        collapseBtn.style.background = 'none';
        collapseBtn.style.border = 'none';
        collapseBtn.style.fontSize = '18px';
        collapseBtn.style.cursor = 'pointer';
        collapseBtn.style.color = '#aaa';
        collapseBtn.addEventListener('click', () => {
            isCollapsed = !isCollapsed;
            contentArea.style.display = isCollapsed ? 'none' : 'flex';
            collapseBtn.textContent = isCollapsed ? '+' : '—';
            container.style.height = isCollapsed ? '30px' : 'auto';
        });

        header.appendChild(title);
        header.appendChild(collapseBtn);

        const contentArea = document.createElement('div');
        contentArea.style.display = 'flex';
        contentArea.style.flexDirection = 'column';
        contentArea.style.gap = '6px';

        const input = document.createElement('input');
        input.type = 'text';
        input.placeholder = '输入关键词';
        input.style.padding = '6px';
        input.style.borderRadius = '4px';
        input.style.border = '1px solid #666';
        input.style.backgroundColor = '#2a2a2a';
        input.style.color = '#fff';

        const scrollSpeedInput = document.createElement('input');
        scrollSpeedInput.type = 'number';
        scrollSpeedInput.placeholder = '滚动速度';
        scrollSpeedInput.min = '100';
        scrollSpeedInput.step = '100';
        scrollSpeedInput.value = scrollStep;
        scrollSpeedInput.style.width = '30%';
        scrollSpeedInput.style.padding = '6px';
        scrollSpeedInput.style.borderRadius = '4px';
        scrollSpeedInput.style.border = '1px solid #666';
        scrollSpeedInput.style.backgroundColor = '#2a2a2a';
        scrollSpeedInput.style.color = '#ccc';
        scrollSpeedInput.title = '滚动步长(像素)';
        scrollSpeedInput.addEventListener('change', () => {
            scrollStep = parseInt(scrollSpeedInput.value) || 1000;
        });

        const searchBtn = document.createElement('button');
        searchBtn.textContent = '开始搜索';
        searchBtn.style.padding = '6px';
        searchBtn.style.backgroundColor = '#007acc';
        searchBtn.style.border = 'none';
        searchBtn.style.color = '#fff';
        searchBtn.style.borderRadius = '4px';
        searchBtn.style.cursor = 'pointer';
        searchBtn.style.width = '48%';

        const stopBtn = document.createElement('button');
        stopBtn.textContent = '停止';
        stopBtn.style.padding = '6px';
        stopBtn.style.backgroundColor = '#c62828';
        stopBtn.style.border = 'none';
        stopBtn.style.color = '#fff';
        stopBtn.style.borderRadius = '4px';
        stopBtn.style.cursor = 'pointer';
        stopBtn.style.width = '48%';

        const statusText = document.createElement('div');
        statusText.textContent = searchStatus;
        statusText.style.fontSize = '12px';
        statusText.style.color = '#aaa';

        contentArea.appendChild(input);
        contentArea.appendChild(scrollSpeedInput);
        contentArea.appendChild(searchBtn);
        contentArea.appendChild(stopBtn);
        contentArea.appendChild(statusText);

        container.appendChild(header);
        container.appendChild(contentArea);
        document.body.appendChild(container);

        let isDragging = false;
        let offsetX, offsetY;

        header.addEventListener('mousedown', (e) => {
            isDragging = true;
            offsetX = e.clientX - container.getBoundingClientRect().left;
            offsetY = e.clientY - container.getBoundingClientRect().top;
        });

        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                container.style.left = (e.clientX - offsetX) + 'px';
                container.style.top = (e.clientY - offsetY) + 'px';
            }
        });
        document.addEventListener('mouseup', () => isDragging = false);

        searchBtn.addEventListener('click', () => {
            const keyword = input.value.trim();
            if (keyword) {
                stopRequested = false;
                currentSearchKeyword = keyword;
                searchStatus = '开始搜索: ' + keyword;
                statusText.textContent = searchStatus;
                processedTweets.clear();
                startScrolling(keyword);
            }
        });

        stopBtn.addEventListener('click', () => {
            stopRequested = true;
            searchStatus = '已停止';
            statusText.textContent = searchStatus;
        });
    }

    async function startScrolling(keyword) {
        const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
        while (!stopRequested) {
            const tweets = document.querySelectorAll('[data-testid="tweet"]');
            for (let tweet of tweets) {
                const textBlock = tweet.querySelector('[data-testid="tweetText"]');
                const tweetText = textBlock?.innerText || '';
                const id = tweet.getAttribute('data-tweet-id') || tweet.innerText.slice(0, 50);
                if (processedTweets.has(id)) continue;
                processedTweets.add(id);
                totalProcessed++;

                if (tweetText.includes(keyword)) {
                    matchCount++;
                    tweet.scrollIntoView({ behavior: 'smooth', block: 'start' });
                    tweet.style.border = '2px solid #ff9632';
                    tweet.style.backgroundColor = '#333';
                    return;
                }
            }
            window.scrollBy({ top: scrollStep, behavior: 'smooth' });
            await delay(600);
        }
    }

    function init() {
        if (!document.getElementById('custom-search-ui')) {
            createSearchUI();
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

})();

QingJ © 2025

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