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)
问题原因分析
- 初始代码的嵌套循环问题:外层遍历所有视频标题,内层却遍历所有视频的元数据,导致每个标题都和所有元数据配对,自然出现大量重复。
- 修改后的代码仍有重复,大概率是因为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
相关产品推荐
相关产品推荐

