您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays YouTube video view counts directly in Google search results
当前为
- // ==UserScript==
- // @name YouTube View Count in Google Search Results
- // @namespace https://github.com/Haris00911/GoogleSearchViewCounter/
- // @version 1.0.0
- // @description Displays YouTube video view counts directly in Google search results
- // @author Haris00911
- // @match https://www.google.com/search*
- // @grant GM_xmlhttpRequest
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_registerMenuCommand
- // @license MIT
- // @homepage https://github.com/Haris00911/GoogleSearchViewCounter/
- // ==/UserScript==
- (function() {
- 'use strict';
- let apiKey = GM_getValue('youtubeApiKey');
- if (!apiKey) {
- apiKey = prompt('Please enter your YouTube Data API key:');
- if (apiKey) {
- GM_setValue('youtubeApiKey', apiKey);
- } else {
- alert('You need to provide an API key for the script to work.');
- return;
- }
- }
- GM_registerMenuCommand('Change YouTube API Key', function() {
- const newKey = prompt('Please enter your YouTube Data API key:', apiKey);
- if (newKey) {
- GM_setValue('youtubeApiKey', newKey);
- apiKey = newKey;
- alert('API key updated. Please reload the page.');
- }
- });
- const processedVideoIDs = new Set();
- const videoIDToLinks = {};
- function getYouTubeVideoID(url) {
- try {
- const urlObj = new URL(url);
- if (urlObj.hostname === 'youtu.be') {
- return urlObj.pathname.substr(1);
- } else if (urlObj.hostname.includes('youtube.com')) {
- return urlObj.searchParams.get('v');
- }
- } catch (e) {
- return null;
- }
- return null;
- }
- function formatViewCount(viewCount) {
- const count = parseInt(viewCount, 10);
- if (count >= 1e9) {
- return (count / 1e9).toFixed(1) + 'B';
- } else if (count >= 1e6) {
- return (count / 1e6).toFixed(1) + 'M';
- } else if (count >= 1e3) {
- return (count / 1e3).toFixed(1) + 'K';
- } else {
- return count.toString();
- }
- }
- function insertViewCount(link, viewCount) {
- const formattedViewCount = formatViewCount(viewCount);
- const span = document.createElement('span');
- span.style.color = '#555';
- span.style.marginLeft = '5px';
- span.textContent = `(${formattedViewCount} views)`;
- // Insert the span after the link
- link.parentNode.insertBefore(span, link.nextSibling);
- }
- function fetchVideoStatistics(videoIDs) {
- const apiURL = 'https://www.googleapis.com/youtube/v3/videos';
- const params = new URLSearchParams();
- params.append('part', 'statistics');
- params.append('id', videoIDs.join(','));
- params.append('key', apiKey);
- const url = `${apiURL}?${params.toString()}`;
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: function(response) {
- if (response.status === 200) {
- const data = JSON.parse(response.responseText);
- if (data.items) {
- data.items.forEach(function(item) {
- const videoID = item.id;
- const viewCount = item.statistics.viewCount;
- const links = videoIDToLinks[videoID];
- if (links) {
- links.forEach(function(link) {
- insertViewCount(link, viewCount);
- });
- }
- });
- }
- } else {
- console.error('Failed to fetch video statistics', response);
- }
- },
- onerror: function(error) {
- console.error('Error fetching video statistics', error);
- }
- });
- }
- function processPage() {
- const searchResults = document.getElementById('search');
- if (!searchResults) return;
- const youtubeLinks = searchResults.querySelectorAll('a[href*="youtube.com/watch?v="], a[href*="youtu.be/"]');
- const videoIDs = new Set();
- youtubeLinks.forEach(function(link) {
- const videoID = getYouTubeVideoID(link.href);
- if (videoID && !processedVideoIDs.has(videoID)) {
- videoIDs.add(videoID);
- processedVideoIDs.add(videoID);
- if (!videoIDToLinks[videoID]) {
- videoIDToLinks[videoID] = [];
- }
- videoIDToLinks[videoID].push(link);
- }
- });
- const videoIDArray = Array.from(videoIDs);
- if (videoIDArray.length === 0) return;
- const batches = [];
- const batchSize = 50;
- for (let i = 0; i < videoIDArray.length; i += batchSize) {
- batches.push(videoIDArray.slice(i, i + batchSize));
- }
- batches.forEach(function(batch) {
- fetchVideoStatistics(batch);
- });
- }
- processPage();
- const observer = new MutationObserver(function(mutations) {
- mutations.forEach(function(mutation) {
- mutation.addedNodes.forEach(function(node) {
- if (node.nodeType === Node.ELEMENT_NODE) {
- if (node.closest('#search')) {
- processPage();
- }
- }
- });
- });
- });
- observer.observe(document.body, { childList: true, subtree: true });
- })();