本文目录导读:

- 方法一:使用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和使用条款,不要过度请求服务器。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播