返回 VideoClaw
file_reader.py
根目录 / video-claw / video-claw / backend / models / file_reader.py
1 # -*- coding: utf-8 -*-
2
3 import os
4 import sys
5
6 models_dir = os.path.dirname(os.path.abspath(__file__))
7 backend_dir = os.path.dirname(models_dir)
8 if backend_dir not in sys.path:
9 sys.path.insert(0, backend_dir)
10
11 import logging
12 from typing import Optional
13 from docx import Document
14
15 logger = logging.getLogger(__name__)
16
17 class FileReader:
18 """
19 文档内容提取工具类
20 """
21
22 @staticmethod
23 def extract_text(file_path: str) -> str:
24 """
25 根据文件后缀名,从文件中提取文本内容
26 支持 .docx, .txt, .md
27 :param file_path: 文件路径
28 :return: 提取出的文本字符串
29 """
30 if not os.path.exists(file_path):
31 logger.error(f"文件不存在: {file_path}")
32 return ""
33
34 ext = os.path.splitext(file_path)[1].lower()
35
36 if ext in [".docx", ".doc"]:
37 return FileReader._extract_docx(file_path)
38 elif ext in [".txt", ".md"]:
39 return FileReader._extract_plain_text(file_path)
40 elif ext == ".pdf":
41 return FileReader._extract_pdf(file_path)
42 else:
43 logger.error(f"不支持的文件格式: {ext}")
44 return ""
45
46 @staticmethod
47 def _extract_docx(file_path: str) -> str:
48 try:
49 doc = Document(file_path)
50 full_text = []
51
52 # 1. 提取所有段落内容
53 for para in doc.paragraphs:
54 cleaned_text = para.text.strip()
55 if cleaned_text:
56 full_text.append(cleaned_text)
57
58 # 2. 提取表格中的内容
59 for table in doc.tables:
60 for row in table.rows:
61 for cell in row.cells:
62 cleaned_cell = cell.text.strip()
63 if cleaned_cell:
64 full_text.append(cleaned_cell)
65
66 return "\n".join(full_text)
67 except Exception as e:
68 logger.error(f"解析 Word 文档失败: {e}")
69 return ""
70
71 @staticmethod
72 def _extract_plain_text(file_path: str) -> str:
73 try:
74 # 尝试使用 multiple encodings
75 for encoding in ['utf-8', 'gbk', 'utf-16']:
76 try:
77 with open(file_path, 'r', encoding=encoding) as f:
78 return f.read()
79 except UnicodeDecodeError:
80 continue
81 return ""
82 except Exception as e:
83 logger.error(f"解析文本文件失败: {e}")
84 return ""
85
86 @staticmethod
87 def _extract_pdf(file_path: str) -> str:
88 try:
89 import PyPDF2
90 text = ""
91 with open(file_path, 'rb') as f:
92 reader = PyPDF2.PdfReader(f)
93 for page in reader.pages:
94 text += page.extract_text() + "\n"
95 return text.strip()
96 except ImportError:
97 logger.error("未安装 PyPDF2,无法解析 PDF 文件。请运行: pip install PyPDF2")
98 return "[错误: 后端未安装 PDF 解析插件]"
99 except Exception as e:
100 logger.error(f"解析 PDF 失败: {e}")
101 return ""
102
103 @staticmethod
104 def format_as_prompt(filename: str, content: str) -> str:
105 """
106 将提取的内容格式化为 LLM Prompt 友好的字符串
107 """
108 if not content:
109 return ""
110
111 return (
112 f"\n--- [上传的文件内容开始] ---\n"
113 f"文件名: {filename}\n"
114 f"内容如下:\n"
115 f"{content}\n"
116 f"--- [上传的文件内容结束] ---\n"
117 )
118
118 lines PYTHON