本文目录导读:

我来为您提供一个批量提取文件摘要信息的Python脚本,支持多种文件格式(文本、PDF、Word、Excel等)。
完整脚本
#!/usr/bin/env python3
"""信息提取工具
支持格式: .txt, .pdf, .docx, .xlsx, .csv, .md, .json, .html 等
"""
import os
import json
import hashlib
import csv
from datetime import datetime
from pathlib import Path
import argparse
import logging
from typing import Dict, List, Any
# 第三方库(需要安装)
try:
import PyPDF2
from docx import Document
import openpyxl
from PIL import Image
import mimetypes
except ImportError as e:
print(f"缺少必要库: {e}")
print("请运行: pip install PyPDF2 python-docx openpyxl pillow")
exit(1)
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('file_extractor.log', encoding='utf-8'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class FileInfoExtractor:
"""文件信息提取器"""
def __init__(self, file_path: str):
self.file_path = Path(file_path)
self.info = {}
def extract_basic_info(self):
"""提取基本信息"""
stat = self.file_path.stat()
self.info = {
'文件名': self.file_path.name,
'文件路径': str(self.file_path),
'文件大小': f"{stat.st_size / 1024:.2f} KB",
'创建时间': datetime.fromtimestamp(stat.st_ctime).strftime('%Y-%m-%d %H:%M:%S'),
'修改时间': datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S'),
'访问时间': datetime.fromtimestamp(stat.st_atime).strftime('%Y-%m-%d %H:%M:%S'),
'文件类型': self.file_path.suffix.lower(),
'MIME类型': mimetypes.guess_type(str(self.file_path))[0] or '未知',
}
# 计算MD5哈希
try:
with open(self.file_path, 'rb') as f:
file_hash = hashlib.md5()
chunk = f.read(8192)
while chunk:
file_hash.update(chunk)
chunk = f.read(8192)
self.info['MD5哈希'] = file_hash.hexdigest()
except Exception as e:
logger.warning(f"计算MD5失败: {e}")
self.info['MD5哈希'] = '计算失败'
# 权限信息
try:
mode = stat.st_mode
self.info['权限'] = oct(mode & 0o777)
except:
self.info['权限'] = '未知'
return self.info
def extract_text_info(self):
"""提取文本文件信息"""
try:
with open(self.file_path, 'r', encoding='utf-8') as f:
content = f.read()
lines = content.split('\n')
# 统计信息
self.info['行数'] = len(lines)
self.info['字符数'] = len(content)
self.info['单词数'] = len(content.split())
# 提取前几行
preview_lines = lines[:10] # 前10行预览
self.info['内容预览'] = preview_lines
# 查找关键信息(简单关键词提取)
keywords = ['作者', '标题', '日期', '版本']
found_keywords = {}
for kw in keywords:
for line in lines[:20]: # 只检查前20行
if kw in line.lower():
found_keywords[kw] = line.strip()
break
if found_keywords:
self.info['关键信息'] = found_keywords
except Exception as e:
logger.error(f"读取文本文件失败: {e}")
self.info['文本内容'] = f'读取失败: {e}'
return self.info
def extract_pdf_info(self):
"""提取PDF文件信息"""
try:
with open(self.file_path, 'rb') as f:
reader = PyPDF2.PdfReader(f)
# 基本信息
self.info['页数'] = len(reader.pages)
# 元数据
meta = reader.metadata
if meta:
self.info['PDF标题'] = meta.title if meta.title else '无'
self.info['PDF作者'] = meta.author if meta.author else '未知'
self.info['PDF主题'] = meta.subject if meta.subject else '无'
self.info['PDF创建者'] = meta.creator if meta.creator else '未知'
# 提取第一页部分文本
if len(reader.pages) > 0:
page = reader.pages[0]
text = page.extract_text()
if text:
preview = text[:300]
self.info['首页内容'] = preview.replace('\n', ' ')
except Exception as e:
logger.error(f"PDF处理失败: {e}")
self.info['PDF信息'] = f'读取失败: {e}'
return self.info
def extract_docx_info(self):
"""提取Word文档信息"""
try:
doc = Document(str(self.file_path))
# 段落数
self.info['段落数'] = len(doc.paragraphs)
self.info['节数'] = len(doc.sections)
# 表格数
self.info['表格数'] = len(doc.tables)
# 统计单词
word_count = 0
for para in doc.paragraphs:
word_count += len(para.text.split())
self.info['单词数'] = word_count
# 提取前几段
preview_paras = []
for i, para in enumerate(doc.paragraphs[:5]):
if para.text.strip():
preview_paras.append(para.text.strip())
self.info['内容预览'] = preview_paras
# 内建属性
props = doc.core_properties
self.info['文档作者'] = props.author if props.author else '未知'
self.info['创建时间'] = props.created if props.created else '未知'
self.info['修改时间'] = props.modified if props.modified else '未知'
except Exception as e:
logger.error(f"Word文档处理失败: {e}")
self.info['Word信息'] = f'读取失败: {e}'
return self.info
def extract_xlsx_info(self):
"""提取Excel表格信息"""
try:
wb = openpyxl.load_workbook(str(self.file_path), read_only=True)
# 工作表信息
sheet_names = wb.sheetnames
self.info['工作表数量'] = len(sheet_names)
self.info['工作表名称'] = sheet_names
# 每个工作表的信息
sheet_info = {}
for sheet_name in sheet_names:
ws = wb[sheet_name]
sheet_info[sheet_name] = {
'行数': ws.max_row,
'列数': ws.max_column,
'数据范围': f"A1:{ws.max_column_letter}{ws.max_row}"
}
# 获取前几行数据
preview_data = []
for row in ws.iter_rows(max_row=3, values_only=True):
preview_data.append(list(row))
sheet_info[sheet_name]['预览数据'] = preview_data
self.info['工作表详情'] = sheet_info
wb.close()
except Exception as e:
logger.error(f"Excel处理失败: {e}")
self.info['Excel信息'] = f'读取失败: {e}'
return self.info
def extract_image_info(self):
"""提取图片信息"""
try:
with Image.open(str(self.file_path)) as img:
self.info['图片格式'] = img.format
self.info['图片尺寸'] = img.size
self.info['图片模式'] = img.mode
# 图像属性
self.info['宽度'] = img.width
self.info['高度'] = img.height
# 获取EXIF信息(如果有)
try:
exif_data = img._getexif()
if exif_data:
# 常见的EXIF标签
exif_labels = {
271: '厂商', 272: '型号', 306: '拍摄时间',
34855: 'ISO', 33434: '曝光时间', 37386: '焦距'
}
exif_info = {}
for tag_id, label in exif_labels.items():
if tag_id in exif_data:
value = exif_data[tag_id]
if tag_id == 33434: # 曝光时间特殊处理
value = f"1/{int(1/float(value))}" if value else f"{value}"
exif_info[label] = value
if exif_info:
self.info['EXIF信息'] = exif_info
except:
pass # 无EXIF信息
except Exception as e:
logger.error(f"图片处理失败: {e}")
self.info['图片信息'] = f'读取失败: {e}'
return self.info
def extract_json_info(self):
"""提取JSON文件信息"""
try:
with open(self.file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
self.info['数据类型'] = type(data).__name__
self.info['数据规模'] = self._count_items(data)
self.info['数据结构'] = self._get_structure_summary(data)
# 可视化预览
preview = json.dumps(data, indent=2, ensure_ascii=False)[:1000]
self.info['内容预览'] = preview
except Exception as e:
logger.error(f"JSON处理失败: {e}")
self.info['JSON信息'] = f'读取失败: {e}'
return self.info
def _count_items(self, data):
"""递归计算数据项数量"""
if isinstance(data, list):
return len(data)
elif isinstance(data, dict):
return len(data)
return 1
def _get_structure_summary(self, data):
"""获取JSON结构摘要"""
if isinstance(data, dict):
keys = list(data.keys())[:10]
structure = f"键值: {keys}"
if len(data) > 10:
structure += f", 共{len(data)}个键"
return structure
elif isinstance(data, list):
structure = f"数组,共{len(data)}个元素"
if len(data) > 0:
structure += f",第一个元素类型: {type(data[0]).__name__}"
return structure
return f"简单类型: {type(data).__name__}"
def extract_all(self):
"""提取所有信息"""
self.extract_basic_info() # 基本信息对任何文件都适用
# 根据文件类型提取特定信息
ext = self.file_path.suffix.lower()
# 文本类文件
if ext in ['.txt', '.md', '.log', '.csv', '.html', '.xml', '.py', '.js', '.css']:
self.extract_text_info()
elif ext == '.pdf':
self.extract_pdf_info()
elif ext == '.docx':
self.extract_docx_info()
elif ext == '.xlsx':
self.extract_xlsx_info()
elif ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp']:
self.extract_image_info()
elif ext == '.json':
self.extract_json_info()
else:
self.info['文件摘要'] = '不支持的特定内容提取'
return self.info
def extract_summary_from_file(file_path: str) -> Dict[str, Any]:
"""从单个文件提取摘要"""
extractor = FileInfoExtractor(file_path)
return extractor.extract_all()
def batch_extract(directory: str, output_format: str = 'json',
output_file: str = None, recursive: bool = False):
"""
批量提取文件摘要
Args:
directory: 要扫描的目录
output_format: 输出格式 (json/csv/excel)
output_file: 输出文件名
recursive: 是否递归处理子目录
"""
# 获取所有文件
base_path = Path(directory)
if recursive:
files = list(base_path.rglob('*'))
else:
files = list(base_path.iterdir())
# 过滤掉目录
files = [f for f in files if f.is_file()]
logger.info(f"找到 {len(files)} 个文件")
results = []
for idx, file_path in enumerate(files, 1):
try:
logger.info(f"[{idx}/{len(files)}] 正在处理: {file_path.name}")
file_info = extract_summary_from_file(file_path)
results.append(file_info)
except Exception as e:
logger.error(f"处理失败 {file_path}: {e}")
results.append({
'文件名': file_path.name,
'文件路径': str(file_path),
'错误信息': str(e)
})
# 输出结果
if output_file:
output_path = Path(output_file)
else:
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
output_path = Path(directory) / f'文件摘要_{timestamp}.{output_format}'
try:
if output_format == 'json':
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2)
elif output_format == 'csv':
# 获取所有可能的键
all_keys = set()
for result in results:
all_keys.update(result.keys())
with open(output_path, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.DictWriter(f, fieldnames=sorted(all_keys))
writer.writeheader()
writer.writerows(results)
elif output_format == 'excel':
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = '文件摘要'
# 创建表头
all_keys = sorted(set().union(*[r.keys() for r in results]))
ws.append(all_keys)
# 写入数据
for row in results:
ws.append([str(row.get(key, '')) for key in all_keys])
# 美化
from openpyxl.styles import Font, Alignment
header_font = Font(bold=True)
for cell in ws[1]:
cell.font = header_font
cell.alignment = Alignment(horizontal='center')
# 自动调整列宽
for column in ws.columns:
max_length = 0
column_letter = column[0].column_letter
for cell in column:
if cell.value:
max_length = max(max_length, len(str(cell.value)))
adjusted_width = min(max_length + 2, 50)
ws.column_dimensions[column_letter].width = adjusted_width
wb.save(output_path)
logger.info(f"摘要已保存到: {output_path}")
return results
except Exception as e:
logger.error(f"保存结果失败: {e}")
return results
def main():
"""主函数"""
parser = argparse.ArgumentParser(
description='批量提取文件摘要信息',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
# 提取当前目录所有文件
python file_extractor.py
# 提取指定目录
python file_extractor.py -d /path/to/directory
# 递归提取子目录
python file_extractor.py -d /path/to/directory -r
# 输出为Excel格式
python file_extractor.py -d /path/to/directory -f excel
# 指定输出文件
python file_extractor.py -d /path/to/directory -o 我的摘要.json
"""
)
parser.add_argument('-d', '--directory',
default='.',
help='要扫描的目录 (默认: 当前目录)')
parser.add_argument('-f', '--format',
choices=['json', 'csv', 'excel'],
default='json',
help='输出格式 (默认: json)')
parser.add_argument('-o', '--output',
help='输出文件路径 (可选)')
parser.add_argument('-r', '--recursive',
action='store_true',
help='递归处理子目录')
args = parser.parse_args()
# 验证目录存在
if not os.path.exists(args.directory):
logger.error(f"目录不存在: {args.directory}")
return
# 执行批量提取
batch_extract(
directory=args.directory,
output_format=args.format,
output_file=args.output,
recursive=args.recursive
)
if __name__ == "__main__":
main()
使用说明
安装依赖
pip install PyPDF2 python-docx openpyxl pillow
基本用法
# 提取当前目录所有文件 python file_extractor.py # 提取指定目录 python file_extractor.py -d /path/to/your/directory # 递归提取子目录 python file_extractor.py -d /path/to/directory -r # 输出为Excel格式 python file_extractor.py -d /path/to/directory -f excel # 指定输出文件名 python file_extractor.py -d /path/to/directory -o 我的摘要.json
功能特点
- 支持格式:PDF、Word、Excel、图片、文本、JSON等多种格式
- 基本信息:文件名、大小、时间、MD5哈希等提取**:根据文件类型提取特定信息
- 多种输出:JSON、CSV、Excel格式
- 递归扫描:可处理子目录
- 日志记录:详细的操作日志
输出示例
输出的JSON文件结构类似于:
[
{
"文件名": "报告.pdf",
"文件路径": "/path/to/报告.pdf",
"文件大小": "245.67 KB",
"创建时间": "2024-01-15 10:30:00",
"文件类型": ".pdf",
"页数": 5,
"PDF标题": "季度报告",
"PDF作者": "张三"
},
...
]
这个脚本可以很好地满足批量提取文件摘要的需求,您可以根据实际需要调整提取的字段和格式。