如何用脚本批量下载视频封面

wen 实用脚本 2

本文目录导读:

如何用脚本批量下载视频封面

  1. 方法一:使用Python + Requests(通用方案)
  2. 方法二:使用yt-dlp(专为YouTube设计)
  3. 方法三:使用FFmpeg从视频提取帧(本地视频)
  4. 方法四:批量下载脚本(命令行版)
  5. 使用说明
  6. 高级选项

我来介绍几种批量下载视频封面图片的方法,涵盖不同技术水平和需求:

使用Python + Requests(通用方案)

import requests
import os
import re
import json
from urllib.parse import urlparse
import time
def download_cover_python(video_urls_file, output_dir="covers"):
    """
    从视频URL列表批量下载封面
    视频URL文件格式:每行一个视频URL
    """
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    # 常见视频平台的封面获取方式
    def get_cover_from_url(url):
        """根据不同的视频平台获取封面URL"""
        # 处理不同的平台
        if 'youtube' in url:
            # YouTube封面格式
            video_id = re.search(r'(?:v=|/)([A-Za-z0-9_-]{11})', url)
            if video_id:
                return f"https://img.youtube.com/vi/{video_id.group(1)}/maxresdefault.jpg"
                # 其他尺寸:0.jpg, 1.jpg, 2.jpg, 3.jpg, default.jpg, hqdefault.jpg, mqdefault.jpg, sddefault.jpg
        elif 'bilibili' in url:
            # B站封面需要通过API获取
            bv_id = re.search(r'(BV[a-zA-Z0-9]+)', url)
            if bv_id:
                api_url = f"https://api.bilibili.com/x/web-interface/view?bvid={bv_id.group(1)}"
                try:
                    response = requests.get(api_url, headers={'User-Agent': 'Mozilla/5.0'})
                    data = response.json()
                    if data['code'] == 0:
                        return data['data']['pic']
                except:
                    return None
        elif 'vimeo' in url:
            # Vimeo需要API访问
            video_id = re.search(r'vimeo\.com/(\d+)', url)
            if video_id:
                return f"https://vumbnail.com/{video_id.group(1)}.jpg"
        elif 'instagram' in url:
            # Instagram需要OAuth
            print("Instagram需要认证,建议使用Instagram Graph API")
            return None
        else:
            # 通用方法:尝试获取页面中的og:image标签
            try:
                headers = {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
                }
                response = requests.get(url, headers=headers)
                match = re.search(r'<meta.*?property="og:image".*?content="([^"]+)"', response.text)
                if match:
                    return match.group(1)
            except:
                return None
        return None
    def download_image(url, filename):
        """下载单张图片"""
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
        try:
            response = requests.get(url, headers=headers, timeout=30)
            if response.status_code == 200:
                with open(filename, 'wb') as f:
                    f.write(response.content)
                return True
        except Exception as e:
            print(f"下载失败 {url}: {e}")
        return False
    # 读取视频URL列表
    with open(video_urls_file, 'r', encoding='utf-8') as f:
        video_urls = [line.strip() for line in f if line.strip()]
    # 逐个下载封面
    for idx, video_url in enumerate(video_urls, 1):
        print(f"处理第 {idx}/{len(video_urls)} 个视频: {video_url}")
        # 获取封面URL
        cover_url = get_cover_from_url(video_url)
        if cover_url:
            # 生成文件名
            filename = os.path.join(output_dir, f"cover_{idx}_{os.path.basename(urlparse(video_url).path)}.jpg")
            if filename.endswith('.jpg') == False:
                filename = filename + '.jpg'
            # 下载图片
            if download_image(cover_url, filename):
                print(f"  成功下载: {filename}")
            else:
                print(f"  下载失败")
        else:
            print("  无法获取封面URL")
        # 延迟避免请求过快
        time.sleep(1)

使用yt-dlp(专为YouTube设计)

# 方法二:使用yt-dlp工具
import subprocess
import os
def download_covers_ytdlp(video_urls_file, output_dir="covers"):
    """使用yt-dlp批量下载YouTube视频封面"""
    # 确保yt-dlp已安装: pip install yt-dlp
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    # 读取视频URL列表
    with open(video_urls_file, 'r', encoding='utf-8') as f:
        video_urls = [line.strip() for line in f if line.strip()]
    for idx, url in enumerate(video_urls, 1):
        print(f"下载第 {idx} 个视频封面: {url}")
        # 使用yt-dlp命令获取封面
        cmd = [
            'yt-dlp',
            '--skip-download',
            '--write-thumbnail',
            '--playlist-items', '1',
            '-o', f'{output_dir}/cover_{idx}.%(ext)s',
            url
        ]
        try:
            subprocess.run(cmd, check=True)
            print(f"  封面已保存到 {output_dir}/cover_{idx}")
        except subprocess.CalledProcessError:
            print(f"  下载失败 {url}")

使用FFmpeg从视频提取帧(本地视频)

def extract_frames_ffmpeg(video_folder, output_folder="frames"):
    """从本地视频批量提取封面帧"""
    import subprocess
    import glob
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    video_files = glob.glob(os.path.join(video_folder, "*.mp4")) + \
                  glob.glob(os.path.join(video_folder, "*.avi")) + \
                  glob.glob(os.path.join(video_folder, "*.mkv"))
    for video in video_files:
        basename = os.path.basename(video).split('.')[0]
        print(f"处理视频: {video}")
        # 提取第一帧作为封面(也可以提取中间帧)
        output_image = os.path.join(output_folder, f"{basename}_cover.jpg")
        # 在第1秒提取一帧
        cmd = [
            'ffmpeg',
            '-i', video,
            '-ss', '00:00:01',  # 从第1秒开始
            '-vframes', '1',
            '-vf', 'scale=1280:-1',  # 调整大小
            '-y',  # 覆盖已存在文件
            output_image
        ]
        try:
            subprocess.run(cmd, check=True, capture_output=True)
            print(f"  已保存封面: {output_image}")
        except subprocess.CalledProcessError as e:
            print(f"  处理失败: {e}")

批量下载脚本(命令行版)

#!/bin/bash
# 批量下载封面脚本 covers_download.sh
# 设置变量
INPUT_FILE="video_list.txt"  # 视频URL列表
OUTPUT_DIR="covers"          # 输出目录
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
# 读取文件并循环处理
count=1
while IFS= read -r url; do
    if [ -n "$url" ]; then
        echo "处理第 $count 个视频: $url"
        # 根据平台使用不同方法
        if [[ "$url" == *"youtube.com"* ]] || [[ "$url" == *"youtu.be"* ]]; then
            # YouTube平台 - 直接构造封面URL
            video_id=$(echo "$url" | grep -o 'v=[^&]*' | cut -d= -f2)
            if [ -z "$video_id" ]; then
                video_id=$(echo "$url" | grep -o '[A-Za-z0-9_-]\{11\}' | head -1)
            fi
            if [ -n "$video_id" ]; then
                curl -s -o "${OUTPUT_DIR}/cover_${count}.jpg" \
                     "https://img.youtube.com/vi/${video_id}/maxresdefault.jpg"
                # 如果上一步失败,尝试其他尺寸
                if [ ! -s "${OUTPUT_DIR}/cover_${count}.jpg" ]; then
                    curl -s -o "${OUTPUT_DIR}/cover_${count}.jpg" \
                         "https://img.youtube.com/vi/${video_id}/hqdefault.jpg"
                fi
            fi
        elif [[ "$url" == *"vimeo.com"* ]]; then
            # Vimeo平台
            video_id=$(echo "$url" | grep -o '[0-9]\{8\}')
            if [ -n "$video_id" ]; then
                curl -s -o "${OUTPUT_DIR}/cover_${count}.jpg" \
                     "https://vumbnail.com/${video_id}.jpg"
            fi
        else
            # 通用方法 - 尝试解析HTML
            curl -s -L "$url" | grep -o '<meta.*property="og:image".*content="[^"]*"' | \
                sed 's/.*content="//;s/"$//' | head -1 | \
                xargs -I{} curl -s -o "${OUTPUT_DIR}/cover_${count}.jpg" "{}"
        fi
        # 检查是否成功
        if [ -s "${OUTPUT_DIR}/cover_${count}.jpg" ]; then
            echo "  成功下载: ${OUTPUT_DIR}/cover_${count}.jpg"
        else
            echo "  下载失败"
        fi
        count=$((count + 1))
        sleep 1  # 延迟
    fi
done < "$INPUT_FILE"
echo "批量下载完成!"

使用说明

创建视频URL列表文件(video_list.txt)

# 每行一个视频URL
https://www.youtube.com/watch?v=xxxxxxxxxxx
https://www.bilibili.com/video/BVxxxxxxxxxxx
https://vimeo.com/12345678
https://www.example.com/video/12345

运行脚本

# Python方法
python cover_downloader.py video_list.txt
# bash方法
chmod +x covers_download.sh
./covers_download.sh
# yt-dlp方法
python ytdlp_cover_downloader.py video_list.txt

安装依赖

# 安装Python依赖
pip install requests
# 安装yt-dlp
pip install yt-dlp
# 安装ffmpeg(用于本地视频提取)
sudo apt-get install ffmpeg  # Ubuntu/Debian
# 或
brew install ffmpeg          # MacOS

高级选项

# 添加并发下载支持
from concurrent.futures import ThreadPoolExecutor
import concurrent.futures
def concurrent_download(video_urls, max_workers=5):
    """并发下载封面"""
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交所有下载任务
        futures = {executor.submit(download_single_cover, url): url 
                   for url in video_urls}
        # 处理结果
        for future in concurrent.futures.as_completed(futures):
            url = futures[future]
            try:
                result = future.result()
                print(f"完成: {url} -> {result}")
            except Exception as e:
                print(f"失败: {url}, 错误: {e}")

这些脚本可以根据你的具体需求进行调整和扩展,记得遵守目标网站的robots.txt和使用条款,不要过度请求服务器。

抱歉,评论功能暂时关闭!