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

如何用JavaScript将YouTube缩略图保存到硬盘?脚本问题求助

YouTube缩略图保存脚本问题解决

问题场景

编写Violentmonkey用户脚本实现YouTube频道缩略图本地保存时遇到跨域问题:

  • Firefox中虽能保存缩略图,但会自动打开图片页面,无法停留在当前YouTube页面
  • Chromium浏览器直接抛出「已被CORS策略阻止」的错误
    需求是直接复用浏览器已下载的缩略图以节省流量,若油猴脚本无法实现,可采用WebExtension方案。

问题根源

  1. 原脚本通过fetch/XHR重新请求ytimg.com域名的缩略图,触发浏览器CORS安全限制,因为ytimg的响应头未允许youtube.com跨域读取资源
  2. 直接使用<a>标签加download属性下载跨域资源时,Firefox会默认打开资源而非触发下载,这是浏览器的跨域安全行为

解决方案

方案一:优化Violentmonkey脚本(复用已加载的图片)

通过Canvas将页面已加载的img元素转为Blob,绕开CORS限制,同时实现无跳转下载:

// ==UserScript==
// @name        保存YouTube频道缩略图
// @namespace   Violentmonkey Scripts
// @match       https://www.youtube.com/*
// @grant       none
// @version     1.1
// @author      -
// @description 直接复用浏览器已加载的缩略图,无跳转保存到本地
// ==/UserScript==

"use strict";

function saveBlob(blob, filename) {
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = filename;
  link.style.display = 'none';
  document.body.appendChild(link);
  // 添加preventDefault阻止可能的跳转
  const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true });
  link.dispatchEvent(clickEvent);
  document.body.removeChild(link);
  // 释放URL对象
  setTimeout(() => URL.revokeObjectURL(link.href), 100);
}

function downloadThumbnail(imgEl, filename) {
  if (!imgEl || !filename) return;
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  // 设置canvas尺寸与图片一致
  canvas.width = imgEl.naturalWidth || imgEl.width;
  canvas.height = imgEl.naturalHeight || imgEl.height;
  // 将图片绘制到canvas
  ctx.drawImage(imgEl, 0, 0);
  // 导出为Blob并保存
  canvas.toBlob((blob) => {
    if (blob) saveBlob(blob, filename);
  }, 'image/webp');
}

function forElement(el) {
  const imgEl = el.querySelector('ytd-thumbnail img');
  if (!imgEl) return;
  // 提取视频标题作为文件名(可选)
  const title = el.querySelector('#video-title').textContent.trim().replace(/[\\/:*?"<>|]/g, '_');
  const filename = `${title}.webp`;
  downloadThumbnail(imgEl, filename);
}

function start() {
  let testButton = document.querySelector("button#test");
  if (!testButton) {
    document.querySelector('ytd-masthead div#container div#end').insertAdjacentHTML(
      'afterbegin',
      '<button id="test" style="padding: 8px 12px; margin-right: 8px; cursor: pointer;">保存缩略图</button>'
    );
    testButton = document.querySelector("button#test");
  }

  testButton.onclick = function() {
    const firstVideoEl = document.querySelectorAll("div#content.ytd-rich-item-renderer")[0];
    if (firstVideoEl) forElement(firstVideoEl);
  };
}

// 监听页面动态加载(YouTube是单页应用)
new MutationObserver(start).observe(document.body, { childList: true, subtree: true });
start();

方案二:WebExtension实现(更稳定)

如果需要批量下载或更可靠的行为,可开发WebExtension,利用浏览器的downloads API直接下载跨域资源:

  1. 在manifest.json中声明权限:
{
  "manifest_version": 3,
  "name": "YouTube缩略图下载器",
  "version": "1.0",
  "permissions": ["downloads"],
  "content_scripts": [
    {
      "matches": ["https://www.youtube.com/*"],
      "js": ["content.js"]
    }
  ]
}
  1. content.js中触发下载:
// 给视频元素添加下载按钮(示例逻辑)
function addDownloadButtons() {
  document.querySelectorAll("div#content.ytd-rich-item-renderer").forEach(el => {
    if (el.querySelector('.thumb-download-btn')) return;
    const btn = document.createElement('button');
    btn.textContent = "存缩略图";
    btn.classList.add('thumb-download-btn');
    btn.style.cssText = 'margin: 8px; padding: 4px; cursor: pointer;';
    btn.onclick = () => {
      const imgUrl = el.querySelector('ytd-thumbnail img').src;
      const title = el.querySelector('#video-title').textContent.trim().replace(/[\\/:*?"<>|]/g, '_');
      // 发送消息给后台脚本调用downloads API
      chrome.runtime.sendMessage({
        url: imgUrl,
        filename: `${title}.webp`
      });
    };
    el.appendChild(btn);
  });
}

// 监听页面变化
new MutationObserver(addDownloadButtons).observe(document.body, { childList: true, subtree: true });
addDownloadButtons();
  1. 后台脚本background.js:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.url && request.filename) {
    chrome.downloads.download({
      url: request.url,
      filename: `YouTube缩略图/${request.filename}`,
      conflictAction: 'uniquify'
    });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:50:36