本文目录导读:

- 方法一:使用Python + Requests(通用方案)
- 方法二:使用yt-dlp(专为YouTube设计)
- 方法三:使用FFmpeg从视频提取帧(本地视频)
- 方法四:批量下载脚本(命令行版)
- 使用说明
- 高级选项
我来介绍几种批量下载视频封面图片的方法,涵盖不同技术水平和需求:
使用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和使用条款,不要过度请求服务器。