import io import os import subprocess import logging import pandas as pd from PIL import Image logger = logging.getLogger("FILE_PARSER") def extract_text_from_file(file_bytes: bytes, filename: str) -> str: """Извлекает текст из изображений (OCR), PDF, таблиц и текстовых файлов.""" ext = os.path.splitext(filename)[1].lower() # Создаем временный файл во избежание проблем с памятью temp_filepath = f"/tmp/upload_{os.getpid()}_{filename}" with open(temp_filepath, "wb") as f: f.write(file_bytes) try: # 1. ИЗОБРАЖЕНИЯ (OCR через системный /usr/bin/tesseract) if ext in ['.png', '.jpg', '.jpeg', '.bmp', '.webp']: cmd = ['tesseract', temp_filepath, 'stdout', '-l', 'rus+eng'] res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) text = res.stdout.strip() return text if text else "[OCR: На изображении не удалось распознать текст]" # 2. PDF ДОКУМЕНТЫ (через системный /usr/bin/pdftotext из poppler-utils) elif ext == '.pdf': cmd = ['pdftotext', temp_filepath, '-'] res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) text = res.stdout.strip() return text if text else "[PDF: Текстовый слой не найден. Возможно, скан без OCR]" # 3. ЭЛЕКТРОННЫЕ ТАБЛИЦЫ (XLSX, CSV через Pandas) elif ext in ['.xlsx', '.xls', '.csv']: if ext == '.csv': df = pd.read_csv(temp_filepath) else: df = pd.read_excel(temp_filepath) total_rows = len(df) df_preview = df.head(100) # Показываем первые 100 строк table_str = df_preview.to_string(index=False) note = f"\n(Показано первых 100 строк из {total_rows})" if total_rows > 100 else "" return f"[СОДЕРЖИМОЕ ТАБЛИЦЫ {filename}]:\n{table_str}{note}" # 4. ТЕКСТОВЫЕ ФАЙЛЫ (TXT, LOG, JSON) elif ext in ['.txt', '.log', '.json', '.xml', '.md']: with open(temp_filepath, 'r', encoding='utf-8', errors='replace') as tf: return tf.read().strip() else: return f"[ОШИБКА: Формат {ext} не поддерживается для анализа]" except Exception as e: logger.error(f"Ошибка при анализе файла {filename}: {e}") return f"[ОШИБКА ОБРАБОТКИ ФАЙЛА: {str(e)}]" finally: if os.path.exists(temp_filepath): os.remove(temp_filepath)