批量提取文件摘要信息的脚本

wen 实用脚本 4

本文目录导读:

批量提取文件摘要信息的脚本

  1. 完整脚本
  2. 使用说明

我来为您提供一个批量提取文件摘要信息的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作者": "张三"
  },
  ...
]

这个脚本可以很好地满足批量提取文件摘要的需求,您可以根据实际需要调整提取的字段和格式。

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