javascript 如何更改打开的youtube视频的窗口标题以包含频道名称?

mwkjh3gx  于 2023-06-20  发布在  Java
关注(0)|答案(2)|浏览(113)

基本上我想要扩展做的是,当我打开一个youtube视频时,抓取youtube频道的名称并将其添加到窗口标题中,这样我就可以只屏蔽一些频道的youtube视频。因此,如果YouTube频道的名称是“马克·罗伯”,视频标题(因此也是窗口标题)是“NASA是在浪费钱吗?“我想把窗口标题改成“NASA是在浪费钱吗?- Mark Rober”.
我试着写了一个chrome扩展,但我不知道如何获得youtube频道的名称,把它放在窗口标题。我尝试使用document.querySelector和document.getElementById,但都返回“null”或undefined。可能是因为我不知道如何访问频道名称,因为它在HTML中没有唯一的ID。
我也想过通过YouTube API来实现这一点,但这需要OAuth令牌。由于这个扩展将非常有助于与许多Web拦截器一起使用,所以我很乐意在它工作时分享它,并且使用可能不太容易访问的令牌(我认为)。
所以如果有人能帮我做到这一点,我会非常感激:)

332nm8kg

332nm8kg1#

我不确定他们的代码中发生了什么,也许ID不是唯一的,但无论如何,我已经设法使用最丑陋的表达式获得了频道的名称:

document.getElementById("primary-inner").children[7].children[1].children[0].children[0].children[0].children[0].children[1].children[0].children[0].children[0].children[0].children[0].innerHTML

(Are你知道页面加载需要时间的问题,如果脚本在页面加载完成之前运行,你可能会得到null?有一些技术可以克服这个问题,如果它对你来说是新的。
编辑:
适用于我的Chrome扩展程序的完整代码:
displayChannelName.js

console.log("displayChannelName started.");

let nodeLoaded = setInterval(function () {
    let node = document.getElementById("primary-inner");
    if (node != undefined) {
        let channelName = node.children[7].children[1].children[0].children[0].children[0].children[0].children[1].children[0].children[0].children[0].children[0].children[0].innerHTML;
        console.log("channel name: " + channelName);
        document.title = document.title + " - " + channelName;
        clearInterval(nodeLoaded);
    };
}, 500);

manifest.json

{
  "name": "YouTube Channel Name",
  "version": "1",
  "description": "Display YouTube Channel Name",
  "manifest_version": 3,
  "content_scripts": [ {
      "matches": ["https://www.youtube.com/watch*"],
      "js": ["displayChannelName.js"]
    } ]
}

编辑:
关于MutationObserver:
displayChannelName.js

console.log("displayChannelName script started.");
let currTitle;

function updateTitle(node) {
    if (document.title != currTitle) {
        console.log("updateTitle function called.");
        if (node == undefined) {
            node = document.getElementById("primary-inner");
        };
        setTimeout(function () { // wait a little in case title changes before the node reloads
            let channelName = node.children[7].children[1].children[0].children[0].children[0].children[0].children[1].children[0].children[0].children[0].children[0].children[0].innerHTML;
            document.title += " - " + channelName;
            currTitle = document.title;
        }, 500);
    };
};

let nodeLoaded = setInterval(function () {
    // update title on page load
    let node = document.getElementById("primary-inner");
    if (node != undefined) {
        updateTitle(node);
        clearInterval(nodeLoaded);
    };
}, 500);

// listen for future changes
new MutationObserver(function (mutations) {
    updateTitle(undefined);
}).observe(
    document.querySelector("title"),
    { subtree: true, characterData: true, childList: true }
);
wj8zmpe1

wj8zmpe12#

我发现Orius提供的代码不再工作了,但却是一个巨大的帮助。
我用一种更简单的方法来选择频道名称并进行了一些改进:
·它现在只删除视频页面上的“-YouTube”文本。
·它将检查频道名称是否已经在标题中并且不再添加它。
·与其他扩展的一些交互导致它将频道名称添加两次。(我有一个脚本,从标题中删除通知号码,以便可能的互动)。当它已经存在时不添加它的相同功能也解决了这个问题。
·以前,只有在新标签页中打开视频时,此功能才有效,因为它仅限于“/watch?v ="清单中的页面。加载主页、订阅等。第一个不会加载扩展,因此当点击视频链接时不会加载,YouTube会将其加载到页面中,而不是正常的页面加载。
它现在加载在所有YouTube页面上,javascript本身会检测到“/watch?v ="change,所以它仍然只改变视频页面的标题,但你现在可以从任何页面开始并点击。
YouTube在页面上留下了视频标题的html,当点击新视频时,通常会交换视频数据,但在非视频页面上,它只是隐藏的垃圾数据,并会导致有关先前观看的视频的信息被添加到标题中。所以这就是为什么标题更改仍然仅限于视频页面的原因。
·还在这里和那里添加了一些检查,以防止在页面上找到数据之前尝试获取数据时出现控制台错误。
这里是版本2
manifest.json

{
  "name": "YouTube Channel Name",
  "version": "2",
  "description": "Display YouTube Channel Name",
  "manifest_version": 3,
  "content_scripts": [ {
      "matches": ["https://www.youtube.com/*"],
      "js": ["displayChannelName.js"]
    } ]
}

displayChannelName.js

console.log("displayChannelName script started.");
let currTitle;

function updateTitle(node) {
    if (window.location.href.indexOf("/watch?v=") > -1) {
        if (document.title != currTitle) {
            console.log("updateTitle function called.");
            if (node == undefined) {
                channelName = (function () { return; })();
                node = document.getElementById("above-the-fold");
            };
            setTimeout(function () { // wait a little in case title changes before the node reloads
                if(node) {
                    document.title = document.title.replace('- YouTube','');
                    channelA = node.querySelector('#channel-name #text a');
                    if(channelA) {
                        let channelName = channelA.innerHTML;
                        console.log('channelName = '+ channelName);
                        if(channelName) {
                            if (document.title.indexOf(channelName) === -1) {
                                document.title += " - " + channelName;
                            }
                        }
                    }
                }
                currTitle = document.title;
            }, 500);
        }
    }
};

let nodeLoaded = setInterval(function () {
    // update title on page load
    let node = document.getElementById("above-the-fold");
    if (node != undefined) {
        updateTitle(node);
        clearInterval(nodeLoaded);
    };
}, 500);

// listen for future changes
new MutationObserver(function (mutations) { 
    updateTitle(undefined);
}).observe(
    document.querySelector("title"),
    { subtree: true, characterData: true, childList: true }
);

相关问题