处理YouTube新视角的评论

时间:2018-01-30 14:29:06

标签: javascript jquery youtube greasemonkey tampermonkey

我正在为Greasemonkey创建一个用户脚本,用于在YouTube中的评论附近显示其他内容。我希望它支持Classic模式和New Look(基于Polymer,可以在https://www.youtube.com/new激活),并且我已经实现了我想要的大部分功能。

但我最近发现的一个主要问题是涉及明显复杂的YouTube机制,涉及以下过程:

  • (1)从缓存中加载第一批评论。

  • (2)从缓存中加载任何其他批注释。

要对每条评论进行处理,我会使用waitForKeyElements来抓住它们 当我不离开当前页面时,这很有效。但是,当我在同一页面上打开不同的视频时,或者当我打开任何其他YouTube页面然后按“返回”时,内容会中断。

导航后,脚本应处理的注释已经处理完毕。当然,这就是YouTube的无重载设计的工作原理。

在某些时候,我能够使脚本识别导航事件yt-navigate-finish - 这解决了问题(1)。但另一个问题(2)仍然存在 - 新批量的评论会出现缓存并重新插入并重新填充。这是我找不到解决方案的地方。

为了演示这个问题,我已经创建了一个小的Greasemonkey脚本(MCVE):

// ==UserScript==
// @name       TEST2
// @include    https://*youtube.com/*
// @require    https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js
// @grant      none
// @run-at     document-start
// ==/UserScript==

waitForKeyElements('#main .style-scope ytd-comment-renderer', ParseItemTest);

function ParseItemTest(jNode) {
    var aNode = $(jNode).find("#author-text")[0];
    var newspan = document.createElement('span');
    newspan.innerHTML = ' <font color="red">===</font> ' + $(aNode).find("span.style-scope.ytd-comment-renderer").html();
  $(aNode).append(newspan);
}

function waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector) {
    var targetNodes, btargetsFound;
    if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt);
    else targetNodes = $(iframeSelector).contents().find(selectorTxt);
    if (targetNodes && targetNodes.length > 0) {
        btargetsFound = true;
        targetNodes.each(function() {
            var jThis = $(this);
            var alreadyFound = jThis.data('alreadyFound') || false;
            if (!alreadyFound) {
                var cancelFound = actionFunction(jThis);
                if (cancelFound) btargetsFound = false;
                else jThis.data('alreadyFound', true);
            }
        });
    } else {
        btargetsFound = false;
    }
    var controlObj = waitForKeyElements.controlObj || {};
    var controlKey = selectorTxt.replace(/[^\w]/g, "_");
    var timeControl = controlObj[controlKey];
    if (btargetsFound && bWaitOnce && timeControl) {
        clearInterval(timeControl);
        delete controlObj[controlKey];
    } else {
        if (!timeControl) {
            timeControl = setInterval(function() {
                waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector);
            }, 300);
            controlObj[controlKey] = timeControl;
        }
    }
    waitForKeyElements.controlObj = controlObj;
}

启用此脚本后,启用YouTube的新外观并转到任何带评论的视频。让他们加载,记下每个评论如何添加用户名,例如

  

Alice === Alice

     

约翰===约翰

     

Grace === Grace

打开任何其他页面并按返回后,您将看到以下内容:

  

Alice === Grace

     

约翰===约翰

     

Grace === Alice

在您转到另一个视频页面并查看评论后,您会看到:

  

Jane === Grace

     

多萝西===约翰

     

布拉德===爱丽丝

我希望这足以解释这个问题。我只需要抓住YouTube用新数据填充现有评论元素的时刻,再用新数据解析它们。

1 个答案:

答案 0 :(得分:0)

感谢你的努力,Brock Adams。

但是我已经提出了类似的解决方案。如果这有助于任何人,这是它的工作原理:

  • 我设置了MutationObserver,以观察<paper-spinner-lite>个对象的变化。
  • 对于每个找到的更改,我会检查孩子div#main.style-scope.ytd-comment-renderer是否有cooldown课程。对我有用的逻辑:
  • 如果是,我会重新检查并重新处理每条评论。
  • 如果不是,我删除每个评论元素。他们会被YouTube正确重新初始化。

(我可以稍后在有空的时候发布实际代码。)