如何检测YouTube上的页面导航并无缝修改其外观?
如何检测YouTube上的页面导航并无缝修改其外观?
我正在制作一个简单的Chrome插件,用于计算YouTube播放列表中每个视频的长度并将总长度插入页面。我已经成功做到了,但是我的脚本只能在刷新页面后才能正常工作,而不能在导航网站时使用。这样并不是很方便。
是否可能在YouTube上检测页面导航并在页面呈现之前插入HTML,以便添加的内容立即显示,无需任何延迟和刷新页面?
示例链接:https://www.youtube.com/playlist?list=PL_8APVyhfhpdgMJ3J80YQxWBMUhbwXw8B
附注:我的问题与Modify elements immediately after they are displayed (not after page completely loads) in greasemonkey script?不同,因为我已经尝试过MutationObserver,问题是相同的-需要刷新才能显示网页的更改:
var observer = new MutationObserver(function(mutations) { for (var i=0; i
如何检测YouTube上的页面导航并无缝地修改其外观?
YouTube网站在导航时不重新加载页面,而是替换历史状态。
当URL更改而没有重新加载页面时,扩展的内容脚本不会被重新注入。当手动重新加载页面时,内容脚本会被执行。
有几种方法可以检测YouTube网站上的页面转换:
- 使用背景页(或MV3服务工作者)脚本:webNavigation API,tabs API
- 在现代Chrome中使用内容脚本和navigatesuccess事件
- 使用内容脚本和站点自己的视频导航事件
为了找到它,让我们在开发者工具控制台中运行getEventListeners(document):
yt-navigate-start是我们在这种情况下需要的。
yt-navigate-finish对其他情况可能更好。
manifest.json:
{
"name": "YouTube Playlist Length",
"version": "0.0.1",
"manifest_version": 2,
"description": ".............",
"content_scripts": [{
"matches": [ "*://*.youtube.com/*" ],
"js": [ "content.js" ],
"run_at": "document_start"
}]
}
注意:matches键包含整个youtube.com域,以便在用户首次打开主页youtube页面然后导航到观看页面时运行内容脚本。
content.js:
document.addEventListener('yt-navigate-start', process);
// 根据需要选择不同的事件应用更改
// document.addEventListener('yt-navigate-finish', process);
if (document.body) process();
else document.addEventListener('DOMContentLoaded', process);
process函数将改变页面。
注意,指定的元素类和结构将来可能会更改。
function process() {
if (!location.pathname.startsWith('/playlist')) {
return;
}
var seconds = [].reduce.call(
document.getElementsByClassName('timestamp'),
function (sum, ts) {
var minsec = ts.textContent.split(':');
return sum + minsec[0] * 60 + minsec[1] * 1;
},
0,
);
if (!seconds) {
console.warn('Got no timestamps. Empty playlist?');
return;
}
var timeHMS = new Date(seconds * 1000).toUTCString().split(' ')[4]
.replace(/^[0:]+/, ''); // trim leading zeroes
document.querySelector('.pl-header-details')
.insertAdjacentHTML('beforeend', '<li>Length: ' + timeHMS + '</li>');
}
参考上面的背景脚本方法:stackoverflow.com/a/21071357/72321
这个解决方案对于YouTube的旧设计效果很好。
网站上有一个新的yt-navigate-start事件显示给一些用户。此外,我稍微概括了答案,以解释如何找到实际事件。
你确定他们使用pushState吗?几天前我快速查看了一下,因为有一个问题(我会找到它并关闭它),但是重写pushState和replaceState,以便在这些方法上包含一个事件发射器根本没有起作用,即使在页面加载之前我重写了它们。
是的,他们只是使用一个iframe来恢复原始API绑定的黑客方法。
哇,聪明,我从未见过(也从未想过)这样的黑客。您知道如果重写是在History proto本身上完成的,这是否也能起作用?
是的,如果你创建一个新的iframe,这个黑客将起作用,因为它将使用原始的浏览器绑定。
很棒的答案,是否有机会在YouTube的移动版本中使用事件监听器方法(因为似乎没有上述提到的监听器可用)?
在2017年,有人提出了一个方法来检测YouTube页面导航并无缝修改其外观。该方法适用于新的Material Design版本的YouTube,以及旧版YouTube。具体的代码如下:
body.addEventListener("yt-navigate-finish", function(event) { // code here }); window.addEventListener("spfdone", function(e) { // code here });
这段代码是从作者编写的两个脚本中提取出来的,分别是"Youtube subtitle downloader"和"Youtube auto subtitle downloader"。作者对这两个脚本进行了测试,证实这两种方法都有效。
如果你对作者的脚本感兴趣并想了解更多细节,可以点击以下链接查看:
[https://github.com/1c7/Youtube-Auto-Subtitle-Download](https://github.com/1c7/Youtube-Auto-Subtitle-Download)
需要注意的是,这个问题的答案已经包含了相关信息,尽管使用了`yt-navigate-start`。虽然这个回答没有涉及原理,但它直接给出了代码,我认为这个答案仍然有一定的价值,所以我会保留这个答案。谢谢提醒。