【问题标题】:Why does the youtube ytplayer object not update when navigating between youtube videos?为什么在 youtube 视频之间导航时 youtube ytplayer 对象不更新?
【发布时间】:2019-07-03 18:40:33
【问题描述】:

我正在开发一个 chrome 扩展,它使用我 contentscript.js 文件中 youtube 页面中的 ytplayer 对象。过去,每次您导航到新的 youtube 视频时,ytplayer 对象都会更新。截至目前,我看不到它再更新了。

如何复制

  1. 转到 chrome 中的 youtube 视频页面(例如,https://www.youtube.com/watch?v=KUh2O8HylUM
  2. 打开开发工具控制台
  3. 在控制台中输入“ytplayer.config.args”
  4. 捕获 ytplayer.config.args 对象
  5. 点击推荐列表中的另一个视频,导航到另一个 youtube 视频。
  6. 再次输入 ytplayer.config.args
  7. 与之前捕获的 ytplayer.config.args 相比

您会看到 ytplayer 在导航到第二个视频后没有更新。我的扩展使用这个对象。问题是该对象在导航到另一个视频后已过时。当我在每次视频导航后拉出 ytplayer 对象时,我会显示错误的数据,因为 ytplayer 总是来自第一个视频。

问题。

  1. 有没有办法获取更新的 ytplayer?

  2. 有没有办法让 ytplayer 重新加载? (我可以在我的 js 代码中添加一个 location.reload() 来解决这个问题,但它很笨拙)

  3. 还有其他方法可以从 chrome 中的 youtube 视频页面获取 ytplayer.conf.args 数据吗?

【问题讨论】:

    标签: javascript google-chrome-extension youtube ytplayer


    【解决方案1】:

    Youtube 是一个现代网站,它仅使用来自服务器的数据来更新页面的一部分。这意味着只有一个完整的页面加载,在此期间ytplayer 是在内联<script> 标记中构建的。这也意味着您的内容脚本只运行一次。

    建议的解决方案是通过覆盖page context中的XHR open方法来拦截站点的网络通信,以获取新的ytplayer对象。

    manifest.json:

    "content_scripts": [{
      "run_at": "document_start",
      "matches": ["https://www.youtube.com/*"],
      "js": ["content.js"]
    }]
    

    content.js:

    const token = chrome.runtime.id + ':' + performance.now() + ':' + Math.random();
    
    window.addEventListener(token, e => {
      console.log('gotPlayerArgs', e.detail);
      chrome.runtime.sendMessage({
        action: 'gotPlayerArgs',
        data: e.detail,
      });
    });
    
    const script = document.createElement('script');
    script.textContent = '(' + (token => {
      const origOpen = XMLHttpRequest.prototype.open;
      const dispatch = data => window.dispatchEvent(new CustomEvent(token, {detail: data}));
      const onLoad = e => {
        const json = e.target.response;
        const player = (Array.isArray(json) && json.find(_ => _.player) || {}).player || {};
        dispatch(player.args);
      };
      // get the initial config
      try {
        dispatch(window.ytplayer.config.args);
      } catch (e) {}
      // intercept the subsequent config queries
      XMLHttpRequest.prototype.open = function (method, url) {
        if (url.startsWith('https://www.youtube.com/watch?')) {
          this.addEventListener('load', onLoad);
        }
        return origOpen.apply(this, arguments);
      };
    }) + `)("${token}")`;
    document.documentElement.appendChild(script);
    script.remove();
    

    仍然存在一个警告:如果 (1) 您的扩展程序已更新/重新加载或禁用/重新启用,并且 (2) youtube 页面不是第一个导航,则初始配置对象将是错误的。要解决此问题,您可以将视频的 id(从 URL 中提取)与配置中的 id(例如“loaderUrl”属性)进行比较,如果不匹配,只需通过 get_video_info 端点获取 args,即易于解析(由& 拆分,然后由= 拆分,然后使用decodeURIComponent): 'https://www.youtube.com/get_video_info?video_id=' + id + '&hl=en_US&html5=1&el=embedded'

    【讨论】:

    • 谢谢!截至目前,我在控制台中不断收到gotPlayerArgs null。不过我会继续玩它的。
    • 我通过将这一行 const player = Array.isArray(json) && json.find(_ => _.player) || {}; 更改为 const player = JSON.parse(json)[2].player 来实现这一点
    • 感谢调试。我在答案中添加了一个不同的修复,因为我不想依赖硬编码的索引。
    猜你喜欢
    • 2013-09-05
    • 2011-08-05
    • 2013-10-23
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2018-10-10
    相关资源
    最近更新 更多