是否有 javascript 删除 Youtube 播放列表中的重复视频?

Is there a javascript to remove duplicate videos in a Youtube playlist?

自从 YouTube discontinued 界面上的 remove duplicates 按钮(大约在同一时间他们停止使用非聚合界面)以来,用户无法删除他们的播放列表。我到处寻找工具来做到这一点,但无济于事。我发现这个脚本可以从播放列表中删除所有视频,想知道是否可以修改它(由比我更了解 javascript 的人修改)以仅删除重复的视频:

setInterval(function () {
  document.querySelector('#primary button[aria-label="Action menu"]').click();
  var things = document.evaluate(
    '//span[contains(text(),"Remove from")]',
    document,
    null,
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
    null
  );
  for (var i = 0; i < things.snapshotLength; i++) {
    things.snapshotItem(i).click();
  }
}, 1000);

实际上(截至 2021-11-07)仍然有一种官方方法可以创建播放列表的新的无重复副本:

  1. 打开 Youtube Music 并创建播放列表 https://music.youtube.com/library/playlists (播放列表需要在youtube music上创建,否则播放列表将在youtube music上不可见...)

  2. 在常规 youtube 上打开您要从中删除重复项的播放列表,例如:https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb

  3. 使用第一个视频的菜单(视频右侧的三个点)并选择“保存到播放列表”并将播放列表的第一个视频保存到新创建的 youtube 音乐播放列表(这是在步骤 1 中创建的)

  4. 将 url 中的 www 替换为 music 以访问旧播放列表的 YouTube 音乐视图,例如:https://music.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb

  5. 使用菜单(三个点)和select“添加到播放列表” 将您的旧播放列表添加到新的(在步骤 1 中创建的)播放列表。由于新播放列表已经包含旧播放列表的视频(在第 3 步中添加),如果您想跳过重复项,您现在会收到一个问题,所以...

  6. ...你select“跳过重复项”。这似乎不仅会跳过最初已包含在您的新播放列表中的视频,而且还会只添加旧播放列表中的每个视频一次,从而删除重复项。


备选方案:Javascript解决方案:

这不是很好,因为它似乎只能在每次按下按钮后进入睡眠状态,但这对我有用:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function removeduplicates() {
    let titles = document.querySelectorAll('#primary #video-title')
    let href_pattern = RegExp('https?://www\.youtube\.com/watch\?v=[^&]*&list=[^&]*&index=')
    titles = Array.from(titles).filter(t => href_pattern.test(t.href))
    let lastid='';
    for (let i = 0; i < titles.length; i++) {
        let id = titles[i].href.match(/\?v=([^&]+)/)[1]
        if(id == lastid){
            titles[i].focus()
            titles[i].parentElement.parentElement.parentElement.parentElement.parentElement.querySelector('button[aria-label="Action menu"]').click()
            await sleep(100)
            var things = document.evaluate(
                '//span[contains(text(),"Remove from")]',
                document,
                null,
                XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                null
            );
            await sleep(300)
            for (var j = 0; j < things.snapshotLength; j++) {
                things.snapshotItem(j).click();
            }
            console.log(titles[i].innerText)
        }
        lastid=id;
    }
}

removeduplicates()

另请注意,它仅在您的语言设置为英语时才有效,因为删除按钮是通过字符串“Remove from”找到的。

要运行这个,您需要在播放列表的播放列表页面(例如https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb),您要从中删除重复项。然后按 F12,将代码粘贴到 javascript 控制台并按回车键。

注意:仅当两个相同的视频紧随其后时,才会删除重复项,因此您需要按例如播放列表排序。视频发布日期。

注意2:只考虑当前加载到浏览器中的视频window,因此您需要向下滚动到播放列表的末尾,这样才能真正加载所有视频。

我实际上使用了脚本并对其进行了一些改进。这个新脚本根本不需要对播放列表进行排序

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
function $$(selector,context=document.documentElement){return[...context?.querySelectorAll?.(selector) ?? []]}

async function removeduplicates() {
    let titles = $$("#primary a#video-title")
    .filter((i,j,k)=>k.
    findIndex(k=>k.href.includes(Object.fromEntries(new URLSearchParams(i.href))['https://www.youtube.com/watch?v']))!==j)
    for (let i = 0; i < titles.length; i++) {
            titles[i].focus()
            titles[i].closest("#contents > *").querySelector('button[aria-label="Action menu"]').click()
            await sleep(100)
            var things = document.evaluate(
                '//span[contains(text(),"Remove from")]',
                document,
                null,
                XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                null
            );
            await sleep(300)
            for (var j = 0; j < things.snapshotLength; j++) {
                things.snapshotItem(j).click();
            }
            console.log(titles[i].innerText)
        }
    }

removeduplicates()

它不检查视频标题,而是检查 hrefs 是否有重复项,仅隔离重复的视频,然后删除重复项。亲自测试过,效果很好