您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
通过检查视频设置菜单识别并筛选YouTube上的4K视频
当前为
// ==UserScript== // @license MIT // @name YouTube 4K 视频过滤器 - 高级版 // @namespace http://tampermonkey.net/ // @version 0.3 // @description 通过检查视频设置菜单识别并筛选YouTube上的4K视频 // @author You // @match https://www.youtube.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_openInTab // ==/UserScript== (function() { 'use strict'; // 存储空间键名 const STORAGE_KEY = 'youtube_4k_videos'; const SCANNING_KEY = 'youtube_4k_scanning'; const buttonId = 'yt-4k-filter-button'; const scanButtonId = 'yt-4k-scan-button'; const badgeClass = 'yt-4k-badge'; // 存储和获取4K视频记录 function saveVideoQuality(videoId, is4K) { const storage = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); storage[videoId] = { is4K: is4K, timestamp: Date.now() }; localStorage.setItem(STORAGE_KEY, JSON.stringify(storage)); console.log(`保存视频 ${videoId} 4K状态: ${is4K}`); } function getVideoQuality(videoId) { const storage = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); return storage[videoId] || null; } function getAllVideoQualities() { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } // 检测是否在视频详情页 function isVideoPage() { return window.location.pathname === '/watch'; } // 检测是否在频道或浏览页面 function isListingPage() { const path = window.location.pathname; return path.includes('/channel/') || path.includes('/c/') || path.includes('/user/') || path.includes('/@') || path === '/' || path.includes('/results') || path.includes('/feed/'); } // 从URL中提取视频ID function extractVideoId(url) { const regExp = /(?:\/|v=)([a-zA-Z0-9_-]{11})(?:\?|&|\/|$)/; const match = url.match(regExp); return match ? match[1] : null; } // 获取当前视频ID function getCurrentVideoId() { if (isVideoPage()) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get('v'); } return null; } // === 视频页面功能 === // 检查当前视频是否有4K选项 async function checkCurrentVideoFor4K() { const videoId = getCurrentVideoId(); if (!videoId) return; // 如果已经检查过此视频,则跳过 const existingData = getVideoQuality(videoId); if (existingData) { console.log(`视频 ${videoId} 已检查过,跳过`); return; } console.log(`检查视频 ${videoId} 是否有4K选项`); try { // 等待视频播放器加载 await waitForElement('button.ytp-settings-button'); // 点击设置按钮 const settingsButton = document.querySelector('button.ytp-settings-button'); settingsButton.click(); await sleep(300); // 点击质量选项 const qualityButton = Array.from(document.querySelectorAll('.ytp-panel-menu .ytp-menuitem')) .find(el => el.textContent.includes('画质') || el.textContent.includes('Quality')); if (qualityButton) { qualityButton.click(); await sleep(300); // 检查是否有4K选项 const qualityOptions = document.querySelectorAll('.ytp-quality-menu .ytp-menuitem'); let has4K = false; qualityOptions.forEach(option => { const text = option.textContent.trim(); if (text.includes('2160p') || text.includes('4K')) { has4K = true; console.log(`发现4K选项: ${text}`); } }); // 保存结果 saveVideoQuality(videoId, has4K); // 关闭菜单 const closeButton = document.querySelector('.ytp-popup .ytp-panel-back-button'); if (closeButton) closeButton.click(); await sleep(100); settingsButton.click(); // 如果是由扫描模式打开的,向列表页面发送消息并关闭此页面 if (isScanningMode()) { // 将此视频标记为已扫描 markVideoAsScanned(videoId); // 1秒后关闭页面 setTimeout(() => { window.close(); }, 1000); } } } catch (error) { console.error('检查视频质量时出错:', error); } } // 等待元素出现 function waitForElement(selector, timeout = 5000) { return new Promise((resolve, reject) => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); observer.observe(document.body, { childList: true, subtree: true }); // 设置超时 setTimeout(() => { observer.disconnect(); reject(new Error(`等待元素 ${selector} 超时`)); }, timeout); }); } // 睡眠函数 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // === 列表页面功能 === // 创建4K过滤按钮 function createFilterButton() { if (document.getElementById(buttonId)) return; console.log('创建4K过滤按钮'); const container = document.createElement('div'); container.id = 'yt-4k-filter-container'; container.style.position = 'fixed'; container.style.top = '120px'; container.style.right = '20px'; container.style.zIndex = '9999'; container.style.display = 'flex'; container.style.flexDirection = 'column'; container.style.gap = '10px'; // 过滤按钮 const filterButton = document.createElement('button'); filterButton.id = buttonId; filterButton.textContent = '显示4K视频'; filterButton.style.padding = '10px 16px'; filterButton.style.backgroundColor = 'red'; filterButton.style.color = 'white'; filterButton.style.border = '2px solid white'; filterButton.style.borderRadius = '4px'; filterButton.style.cursor = 'pointer'; filterButton.style.fontWeight = 'bold'; filterButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.5)'; filterButton.addEventListener('click', toggleFilter); // 扫描按钮 const scanButton = document.createElement('button'); scanButton.id = scanButtonId; scanButton.textContent = '扫描4K视频'; scanButton.style.padding = '10px 16px'; scanButton.style.backgroundColor = 'blue'; scanButton.style.color = 'white'; scanButton.style.border = '2px solid white'; scanButton.style.borderRadius = '4px'; scanButton.style.cursor = 'pointer'; scanButton.style.fontWeight = 'bold'; scanButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.5)'; scanButton.addEventListener('click', startScanningVideos); // 状态显示 const statusDisplay = document.createElement('div'); statusDisplay.id = 'yt-4k-status'; statusDisplay.style.backgroundColor = 'rgba(0,0,0,0.7)'; statusDisplay.style.color = 'white'; statusDisplay.style.padding = '8px'; statusDisplay.style.borderRadius = '4px'; statusDisplay.style.fontSize = '12px'; statusDisplay.style.display = 'none'; container.appendChild(filterButton); container.appendChild(scanButton); container.appendChild(statusDisplay); document.body.appendChild(container); } // 更新状态显示 function updateStatus(message, show = true) { const statusEl = document.getElementById('yt-4k-status'); if (statusEl) { statusEl.textContent = message; statusEl.style.display = show ? 'block' : 'none'; } } // 切换过滤状态 let filterActive = false; function toggleFilter() { filterActive = !filterActive; const button = document.getElementById(buttonId); if (filterActive) { button.textContent = '显示所有视频'; button.style.backgroundColor = 'green'; const storage = getAllVideoQualities(); let count4K = 0; // 筛选视频 const videoElements = document.querySelectorAll('ytd-grid-video-renderer, ytd-rich-item-renderer, ytd-video-renderer'); videoElements.forEach(video => { const linkElement = video.querySelector('a#thumbnail') || video.querySelector('a.yt-simple-endpoint'); if (!linkElement || !linkElement.href) return; const videoId = extractVideoId(linkElement.href); if (!videoId) return; const qualityData = storage[videoId]; const is4K = qualityData && qualityData.is4K; if (is4K) { count4K++; // 添加4K标记 if (!video.querySelector(`.${badgeClass}`)) { addBadgeToVideo(video, linkElement); } video.style.display = ''; } else { video.style.display = 'none'; } }); updateStatus(`找到 ${count4K} 个4K视频`); } else { button.textContent = '显示4K视频'; button.style.backgroundColor = 'red'; // 恢复所有视频显示 document.querySelectorAll('ytd-grid-video-renderer, ytd-rich-item-renderer, ytd-video-renderer').forEach(video => { video.style.display = ''; }); updateStatus('', false); } } // 为视频添加4K标记 function addBadgeToVideo(videoElement, linkElement) { const badge = document.createElement('div'); badge.className = badgeClass; badge.textContent = '4K'; badge.style.position = 'absolute'; badge.style.top = '5px'; badge.style.right = '5px'; badge.style.backgroundColor = 'red'; badge.style.color = 'white'; badge.style.padding = '3px 6px'; badge.style.borderRadius = '3px'; badge.style.fontWeight = 'bold'; badge.style.fontSize = '12px'; badge.style.zIndex = '2'; if (linkElement) { linkElement.style.position = 'relative'; linkElement.appendChild(badge); } } // 扫描功能 function isScanningMode() { return localStorage.getItem(SCANNING_KEY) === 'true'; } function setScanningMode(isScanning) { localStorage.setItem(SCANNING_KEY, isScanning ? 'true' : 'false'); } function markVideoAsScanned(videoId) { const scannedVideos = JSON.parse(localStorage.getItem('scanned_videos') || '[]'); if (!scannedVideos.includes(videoId)) { scannedVideos.push(videoId); localStorage.setItem('scanned_videos', JSON.stringify(scannedVideos)); } } function isVideoScanned(videoId) { const scannedVideos = JSON.parse(localStorage.getItem('scanned_videos') || '[]'); return scannedVideos.includes(videoId); } async function startScanningVideos() { const scanButton = document.getElementById(scanButtonId); if (isScanningMode()) { // 停止扫描 setScanningMode(false); scanButton.textContent = '扫描4K视频'; scanButton.style.backgroundColor = 'blue'; updateStatus('扫描已停止', true); setTimeout(() => updateStatus('', false), 3000); return; } // 开始扫描 setScanningMode(true); scanButton.textContent = '停止扫描'; scanButton.style.backgroundColor = 'orange'; // 获取页面上的所有视频 const videoElements = document.querySelectorAll('ytd-grid-video-renderer, ytd-rich-item-renderer, ytd-video-renderer'); const totalVideos = videoElements.length; let scannedCount = 0; let pendingCount = 0; // 清除已扫描记录 localStorage.setItem('scanned_videos', '[]'); // 遍历视频元素 for (let i = 0; i < videoElements.length; i++) { if (!isScanningMode()) break; // 如果扫描被中止则退出 const video = videoElements[i]; const linkElement = video.querySelector('a#thumbnail') || video.querySelector('a.yt-simple-endpoint'); if (!linkElement || !linkElement.href) continue; const videoId = extractVideoId(linkElement.href); if (!videoId) continue; // 检查是否已经知道此视频的4K状态 const qualityData = getVideoQuality(videoId); if (qualityData) { scannedCount++; updateStatus(`扫描进度: ${scannedCount}/${totalVideos},已知视频跳过`); continue; } // 在新标签页中打开视频 updateStatus(`扫描进度: ${scannedCount}/${totalVideos},打开视频 ${videoId}`); // 限制并发标签页数量 pendingCount++; if (pendingCount >= 3) { // 等待至少一个视频被扫描 await waitForAnyVideoScanned(); pendingCount--; } // 打开新标签页 window.open(`https://www.youtube.com/watch?v=${videoId}`, '_blank'); // 等待一段时间再继续 await sleep(1500); } // 扫描完成 setScanningMode(false); scanButton.textContent = '扫描4K视频'; scanButton.style.backgroundColor = 'blue'; updateStatus('扫描完成!', true); setTimeout(() => updateStatus('', false), 5000); } // 等待任意视频被扫描 function waitForAnyVideoScanned() { return new Promise(resolve => { const initialCount = JSON.parse(localStorage.getItem('scanned_videos') || '[]').length; const checkInterval = setInterval(() => { const currentCount = JSON.parse(localStorage.getItem('scanned_videos') || '[]').length; if (currentCount > initialCount || !isScanningMode()) { clearInterval(checkInterval); resolve(); } }, 500); // 设置超时,避免永久等待 setTimeout(() => { clearInterval(checkInterval); resolve(); }, 10000); }); } // 标记已知的4K视频 function markKnown4KVideos() { if (filterActive) return; // 如果正在过滤则跳过 const storage = getAllVideoQualities(); const videoElements = document.querySelectorAll('ytd-grid-video-renderer, ytd-rich-item-renderer, ytd-video-renderer'); videoElements.forEach(video => { const linkElement = video.querySelector('a#thumbnail') || video.querySelector('a.yt-simple-endpoint'); if (!linkElement || !linkElement.href) return; const videoId = extractVideoId(linkElement.href); if (!videoId) return; const qualityData = storage[videoId]; if (qualityData && qualityData.is4K && !video.querySelector(`.${badgeClass}`)) { addBadgeToVideo(video, linkElement); } }); } // === 初始化 === // 根据页面类型初始化功能 function init() { if (isVideoPage()) { // 视频详情页 checkCurrentVideoFor4K(); } else if (isListingPage()) { // 视频列表页 createFilterButton(); markKnown4KVideos(); // 监听DOM变化 const observer = new MutationObserver(mutations => { if (!document.getElementById(buttonId)) { createFilterButton(); } // 延迟执行,避免频繁调用 clearTimeout(window.markTimeout); window.markTimeout = setTimeout(() => { markKnown4KVideos(); if (filterActive) toggleFilter(); }, 1000); }); observer.observe(document.body, { childList: true, subtree: true }); } } // 启动程序 function start() { console.log('YouTube 4K 过滤器启动'); // 尝试多次初始化,确保在页面加载后运行 setTimeout(init, 5000); // 监听URL变化 let lastUrl = location.href; const urlObserver = new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href; // URL变化时重新初始化 setTimeout(init, 1500); } }); urlObserver.observe(document.body, { subtree: true, childList: true }); } start(); })();