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

Chrome控制台JS爬取YouTube视频信息去重问题求助

修复YouTube频道视频数据爬取中的重复问题

问题描述

我想在Chrome开发者控制台编写JavaScript代码,爬取YouTube频道视频页面的所有视频标题、链接(href)和元数据信息。最初用嵌套循环的代码能正确输出元数据,但标题和链接会重复输出之前循环的内容;后来改成遍历每个视频容器节点获取对应信息,可还是有重复数据被推入数组,求修复方法。

复现步骤:

  • 打开YouTube
  • 进入某个特定频道
  • 切换到该频道的「视频」标签页
  • (可选)执行滚动到底部的代码,获取更多数据
  • 在控制台粘贴代码并运行

初始代码:

$('.ytd-grid-video-renderer').find('#video-title').each(function() {
  const v1 = $(this).attr('title')
  $('.ytd-grid-video-renderer').find('#metadata-line').each(function() {
    const v2 = $(this).text()
    console.log(`title: ${v1}, meta: ${v2}}`)
  })
})

修改后代码:

let myArr = []
$('.ytd-grid-video-renderer').each(function() {
  const v1 = $(this).find('#video-title').attr('title');
  const v2 = $(this).find('#metadata-line').text();
  if (v1 && v2) {
    myArr.push(`{title: ${v1}, meta: ${v2}}`)
  }
})

console.log(myArr)

问题原因分析

  1. 初始代码的嵌套循环问题:外层遍历所有视频标题,内层却遍历所有视频的元数据,导致每个标题都和所有元数据配对,自然出现大量重复。
  2. 修改后的代码仍有重复,大概率是因为YouTube的DOM结构中,ytd-grid-video-renderer可能存在重复节点(比如加载更多时的临时节点、隐藏的缓存节点),或者你滚动时重复执行代码没清空数组,导致旧数据残留。另外,你现在的代码还没处理视频链接(href)的获取。

修复方案

1. 确保遍历唯一的视频容器,清理数组并添加链接获取

每次执行代码前清空数组,避免重复执行时旧数据残留;用更精准的选择器定位视频容器,同时获取视频的href链接:

// 每次执行前清空数组,避免重复数据
let myArr = [];
// 只选中可见的视频容器,过滤隐藏的缓存节点
$('ytd-grid-video-renderer:visible').each(function() {
  const $video = $(this);
  const title = $video.find('#video-title').attr('title');
  const href = $video.find('#video-title').attr('href');
  const metadata = $video.find('#metadata-line').text().trim();
  
  // 确保三个字段都存在,再通过标题+链接的组合判断是否重复
  if (title && href && metadata) {
    const isDuplicate = myArr.some(item => item.title === title && item.href === href);
    if (!isDuplicate) {
      myArr.push({ title, href: `https://youtube.com${href}`, metadata });
    }
  }
});

console.log(myArr);

2. 滚动加载的辅助代码(可选)

如果需要自动滚动加载所有视频,可以先执行这段代码,等滚动停止后再执行爬取代码:

// 自动滚动到底部加载所有视频
function scrollToLoadAll() {
  const scrollHeight = document.documentElement.scrollHeight;
  window.scrollTo(0, scrollHeight);
  // 检查是否还能继续滚动,递归调用直到加载完成
  setTimeout(() => {
    if (document.documentElement.scrollHeight > scrollHeight) {
      scrollToLoadAll();
    } else {
      console.log('所有视频加载完成,可以执行爬取代码了');
    }
  }, 1000);
}

scrollToLoadAll();

3. 替代方案:使用原生JS而非jQuery(避免依赖)

如果YouTube页面环境移除了jQuery,用原生JS也能实现:

let myArr = [];
const videoContainers = document.querySelectorAll('ytd-grid-video-renderer:is(:visible)');

videoContainers.forEach(container => {
  const titleEl = container.querySelector('#video-title');
  const title = titleEl?.getAttribute('title');
  const href = titleEl?.getAttribute('href');
  const metadata = container.querySelector('#metadata-line')?.textContent.trim();
  
  if (title && href && metadata) {
    const isDuplicate = myArr.some(item => item.title === title && item.href === href);
    if (!isDuplicate) {
      myArr.push({
        title,
        href: `https://youtube.com${href}`,
        metadata
      });
    }
  }
});

console.log(myArr);

关键注意点

  • 每次执行爬取代码都要初始化myArr = [],避免重复执行时旧数据残留。
  • 用:visible选择器过滤隐藏节点,避免抓取DOM中缓存的重复元素。
  • 通过标题+链接的组合判断重复,因为不同视频可能标题相同,但链接绝对唯一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:35:32