我正在使用Chrome扩展程序,该扩展程序使用contentscript.js文件中youtube页面上的ytplayer对象。过去,每次您浏览到新的youtube视频时,ytplayer对象都会更新。到目前为止,我看不到它有任何更新。

如何复制

  • 转到chrome上的youtube视频页面(例如https://www.youtube.com/watch?v=KUh2O8HylUM)
  • 打开开发工具控制台
  • 在控制台中输入“ytplayer.config.args”
  • 捕获ytplayer.config.args对象
  • 通过从推荐列表中单击其他视频,导航到另一个youtube视频。
  • 再次输入ytplayer.config.args
  • 与之前捕获的ytplayer.config.args比较

  • 您会看到导航到第二个视频后ytplayer不会更新。我的扩展程序使用此对象。问题在于,导航到另一个视频后,该对象已陈旧。每次视频导航后,我拉ytplayer对象时,都会显示错误的数据,因为ytplayer始终来自第一个视频。

    问题。
  • 有没有办法获取更新的ytplayer?
  • 有没有办法让ytplayer重新加载? (我可以在我的js代码中添加一个location.reload(),以解决此问题,但它既笨拙又la脚)
  • 是否有另一种方法可以从Chrome的youtube视频页面获取ytplayer.conf.args数据?
  • 最佳答案

    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中提取)与config内部的ID(例如“loaderUrl”属性)进行比较,如果不匹配,只需通过get_video_info端点获取args,易于解析(先由&分割,然后由=分割,然后使用encodeURIComponent):'https://www.youtube.com/get_video_info?video_id=' + id + '&hl=en_US&html5=1&el=embedded'

    关于javascript - 在youtube视频之间导航时,为什么youtube ytplayer对象不更新?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54610750/

    10-09 14:21