You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展中用JavaScript获取YouTube视频标题失败求助

问题:Chrome扩展Content Script无法获取YouTube视频标题子元素

我正在学习开发Chrome扩展,想要实现一个能在控制台打印当前YouTube视频标题的简单扩展。页面中YouTube标题的HTML结构如下:

<div id="title" class="style-scope ytd-watch-metadata">
    <ytd-badge-supported-renderer class="style-scope ytd-watch-metadata" disable-upgrade="" hidden="">
    </ytd-badge-supported-renderer>
    <h1 class="style-scope ytd-watch-metadata">
      <yt-formatted-string force-default-style="" class="style-scope ytd-watch-metadata">Elon’s "based" Grok AI has entered the chat…</yt-formatted-string>
    </h1>
    <ytd-badge-supported-renderer class="style-scope ytd-watch-metadata" disable-upgrade="" hidden="">
    </ytd-badge-supported-renderer>
</div>

我在Content Script中编写了如下代码:

(()=>{
    console.log(document.getElementById("title"));
    console.log(document.querySelector("#title > h1 > yt-formatted-string"));
})();

执行后第一行能输出title元素,但第二行获取子元素返回null。在Chrome控制台直接输入该代码能得到正确结果。我尝试过DOMContentLoaded等方法,均无效,manifest.json配置如下:

{
    "manifest_version": 3,
    "name": "FillModule",
    "description": "Fill test 001",
    "version": "1.0.0",
    "permissions": ["storage", "tabs"],
    "author":"Aniket Vishwakarma",
    "action": {
        "default_icon": "assets/doggy.png",
        "default_title": "Fill",
        "default_popup": "popup/popup.html"
    },
    "background" : {
        "service_worker": "background/background.js"
    },
    "content_scripts": [
        {
          "matches": ["https://*.youtube.com/*"],
          "js": ["content/content.js"]
        }
    ]
}

原因分析

  • YouTube是单页应用(SPA),视频页面的核心内容通过JavaScript动态渲染。Content Script默认在初始DOM加载完成后执行,但此时标题的子元素(h1和yt-formatted-string)还未被插入到DOM中。
  • DOMContentLoaded事件仅监听初始DOM树加载完成,无法感知后续通过JS动态插入的内容。
  • 直接在控制台执行代码时,页面已完全渲染完毕,所有动态内容都已加载,因此能正常获取目标元素。

解决方案

方法1:使用MutationObserver监听DOM变化

通过监听title元素的子节点变化,当目标子元素出现时立即获取并停止监听:

(() => {
  const titleDiv = document.getElementById('title');
  if (!titleDiv) return;

  const observer = new MutationObserver((mutations) => {
    const targetElement = titleDiv.querySelector('h1 > yt-formatted-string');
    if (targetElement) {
      console.log('视频标题:', targetElement.textContent);
      observer.disconnect(); // 获取到元素后停止监听,避免重复触发
    }
  });

  // 监听title元素的子节点变化,包括子树内的变化
  observer.observe(titleDiv, {
    childList: true,
    subtree: true
  });
})();

方法2:定时检查目标元素

通过定时轮询的方式,直到目标元素出现为止:

(() => {
  function getVideoTitle() {
    const titleElement = document.querySelector('#title > h1 > yt-formatted-string');
    if (titleElement) {
      console.log('视频标题:', titleElement.textContent);
    } else {
      setTimeout(getVideoTitle, 500); // 每隔500毫秒检查一次
    }
  }
  getVideoTitle();
})();

方法3:监听YouTube自定义导航事件

YouTube提供了自定义的yt-navigate-finish事件,用于标记SPA页面切换完成,可通过监听该事件重新获取标题:

(() => {
  function handlePageLoad() {
    const titleElement = document.querySelector('#title > h1 > yt-formatted-string');
    if (titleElement) {
      console.log('视频标题:', titleElement.textContent);
    }
  }

  // 页面初始加载时执行一次
  handlePageLoad();

  // 监听SPA页面切换事件,切换视频时重新获取标题
  document.addEventListener('yt-navigate-finish', handlePageLoad);
})();

内容的提问来源于stack exchange,提问作者Aniket Vishwakarma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:55:06