
在 AWS S3(Simple Storage Service)中管理大量文件时,经常需要统计特定目录或符合特定命名规则的文件数量。例如,对于视频切片存储场景,可能需要验证每个视频质量版本(如 144p, 360p)下是否存在预期数量的切片文件(如 file_000.ts, file_001.ts 等)。手动检查这些文件既耗时又容易出错,因此编写自动化脚本变得尤为重要。
Python 的 boto3 库是与 AWS 服务交互的官方 SDK,提供了强大的功能来操作 S3。然而,在使用 boto3 进行文件计数时,尤其是在文件数量庞大且分散在多个“文件夹”中时,需要注意一些关键点,如分页处理和精确的文件名匹配。
在最初尝试使用 boto3.client().list_objects_v2 方法时,可能会遇到以下挑战:
boto3.resource 接口提供了更高级别的抽象,相较于 boto3.client,它更面向对象,并能自动处理许多底层细节,包括分页。这使得代码更简洁、更易读。
立即学习“Python免费学习笔记(深入)”;
以下是一个使用 boto3.resource 统计 S3 桶中特定前缀下,符合 file_*.ts 模式文件数量的基本函数:
import boto3
def count_specific_files_in_s3(bucket_name, s3_prefix, file_name_starts_with='file_', file_name_ends_with='.ts'):
"""
统计S3桶中指定前缀下,符合特定命名模式的文件数量。
Args:
bucket_name (str): S3 桶的名称。
s3_prefix (str): 要搜索的S3前缀(即“文件夹”路径)。
例如:'Financial_Freedom_Course_Kannada/00_Course_Trailer_New_update/144p/'
file_name_starts_with (str): 文件名应以此字符串开头。
file_name_ends_with (str): 文件名应以此字符串结尾。
Returns:
int: 符合条件的文件数量。
"""
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)
actual_count = 0
print(f"正在检查 S3 路径: s3://{bucket_name}/{s3_prefix}...")
# 使用 Prefix 进行服务器端初步过滤
# bucket.objects.filter() 会自动处理分页
for obj in bucket.objects.filter(Prefix=s3_prefix):
# 进一步在客户端过滤,确保符合命名约定且不是S3模拟的文件夹对象
# S3中没有真正的文件夹,以'/'结尾的键通常被视为文件夹
if obj.key.startswith(f'{s3_prefix}{file_name_starts_with}') and \
obj.key.endswith(file_name_ends_with) and \
not obj.key.endswith('/'): # 排除S3模拟的文件夹对象
actual_count += 1
# print(f" 找到匹配文件: {obj.key}") # 可用于调试
return actual_count
# 示例用法 (请替换为您的实际桶名和前缀)
# fixed_bucket_name = 'your-s3-bucket-name'
# example_prefix = 'your-folder-path/sub-folder/'
# count = count_specific_files_in_s3(fixed_bucket_name, example_prefix)
# print(f"在 s3://{fixed_bucket_name}/{example_prefix} 路径下找到 {count} 个文件。")结合原始问题中从 CSV 读取 URL 并写入结果的需求,我们可以构建一个完整的脚本来自动化这一过程。
假设 ldt_ffw_course_videos_temp.csv 文件包含以下结构:
course_video_s3_url,course_video_ts_file_cnt Financial_Freedom_Course_Kannada/00_Course_Trailer_New_update/144p/,28 Financial_Freedom_Course_Kannada/00_Course_Trailer_New_update/360p/,54 Financial_Freedom_Course_Kannada/00_Course_Trailer_New_update/720p/,34
其中 course_video_s3_url 是相对于 S3 桶根目录的路径,course_video_ts_file_cnt 是该路径下期望的文件数量。
import csv
import boto3
from urllib.parse import urlparse # 用于解析S3 URL,如果需要
# 辅助函数:解析 S3 URL 获取桶名和前缀 (如果输入CSV中是完整S3 URL)
def parse_s3_url(s3_url):
"""从完整的S3 URL中解析出桶名和前缀路径。"""
parsed = urlparse(s3_url)
if parsed.scheme != 's3':
raise ValueError("URL 必须以 's3://' 开头。")
bucket_name = parsed.netloc
# path 包含前导斜杠,需要去除
prefix = parsed.path.lstrip('/')
return bucket_name, prefix
# 改进的计数函数 (与上面示例相同)
def count_specific_files_in_s3(bucket_name, s3_prefix, file_name_starts_with='file_', file_name_ends_with='.ts'):
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)
actual_count = 0
for obj in bucket.objects.filter(Prefix=s3_prefix):
if obj.key.startswith(f'{s3_prefix}{file_name_starts_with}') and \
obj.key.endswith(file_name_ends_with) and \
not obj.key.endswith('/'):
actual_count += 1
return actual_count
# 输入和输出 CSV 文件名
input_csv_file = 'ldt_ffw_course_videos_temp.csv'
output_csv_file = 'file_count_result.csv'
# 假设 S3 桶名是固定的。请替换为您的实际桶名。
# 如果您的CSV中包含完整的S3 URL (如 s3://bucket-name/path/...), 则可以使用 parse_s3_url 函数动态获取桶名。
fixed_bucket_name = 'coursevideotesting' # 替换为你的S3桶名
# 主处理逻辑
try:
with open(input_csv_file, mode='r', encoding='utf-8') as infile, \
open(output_csv_file, mode='w', newline='', encoding='utf-8') as outfile:
reader = csv.DictReader(infile)
# 验证输入CSV文件是否包含必要的列
required_columns = ['course_video_s3_url', 'course_video_ts_file_cnt']
if not all(col in reader.fieldnames for col in required_columns):
raise ValueError(f"输入CSV文件必须包含以下列: {', '.join(required_columns)}")
#以上就是使用 Python 和 Boto3 库高效统计 AWS S3 存储桶中特定文件的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号