Spaces:
Sleeping
Sleeping
File size: 5,936 Bytes
86c402d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
"""
Модуль с универсальным парсером, объединяющим все специфичные парсеры.
"""
import logging
import os
from typing import BinaryIO
from ..data_classes import ParsedDocument
from .abstract_parser import AbstractParser
from .file_types import FileType
from .parser_factory import ParserFactory
from .specific_parsers import (
DocParser,
DocxParser,
EmailParser,
HTMLParser,
MarkdownParser,
PDFParser,
XMLParser,
)
logger = logging.getLogger(__name__)
class UniversalParser:
"""
Универсальный парсер, объединяющий все специфичные парсеры.
Использует фабрику парсеров для выбора подходящего парсера
на основе типа файла.
"""
def __init__(self):
"""
Инициализирует универсальный парсер и регистрирует все доступные парсеры.
"""
self.factory = ParserFactory()
# Регистрируем все доступные парсеры
self.register_parsers(
[
XMLParser(), # Реализованный парсер
PDFParser(), # Нереализованный парсер
DocParser(), # Нереализованный парсер
DocxParser(), # Реализованный парсер
EmailParser(), # Нереализованный парсер
MarkdownParser(), # Нереализованный парсер
HTMLParser(), # Нереализованный парсер
]
)
def register_parser(self, parser: AbstractParser) -> None:
"""
Регистрирует парсер в фабрике.
Args:
parser (AbstractParser): Парсер для регистрации.
"""
self.factory.register_parser(parser)
def register_parsers(self, parsers: list[AbstractParser]) -> None:
"""
Регистрирует несколько парсеров в фабрике.
Args:
parsers (list[AbstractParser]): Список парсеров для регистрации.
"""
for parser in parsers:
self.register_parser(parser)
def parse_by_path(self, file_path: str) -> ParsedDocument | None:
"""
Парсит документ по пути к файлу, используя подходящий парсер.
Args:
file_path (str): Путь к файлу для парсинга.
Returns:
ParsedDocument | None: Структурное представление документа или None,
если подходящий парсер не найден.
Raises:
ValueError: Если файл не существует или не может быть прочитан.
"""
if not os.path.exists(file_path):
raise ValueError(f"Файл не найден: {file_path}")
# Находим подходящий парсер
parser = self.factory.get_parser(file_path)
if not parser:
logger.warning(f"Не найден подходящий парсер для файла: {file_path}")
return None
# Парсим документ
try:
return parser.parse_by_path(file_path)
except Exception as e:
logger.error(f"Ошибка при парсинге файла {file_path}: {e}")
raise
def parse(
self, file: BinaryIO, file_type: FileType | str | None = None
) -> ParsedDocument | None:
"""
Парсит документ из объекта файла, используя подходящий парсер.
Args:
file (BinaryIO): Объект файла для парсинга.
file_type: Тип файла, может быть объектом FileType или строкой с расширением.
Например: FileType.XML или ".xml"
Returns:
ParsedDocument | None: Структурное представление документа или None,
если подходящий парсер не найден.
Raises:
ValueError: Если файл не может быть прочитан или распарсен.
"""
# Преобразуем строковое расширение в FileType, если нужно
ft = None
if isinstance(file_type, str):
try:
ft = FileType.from_extension(file_type)
except ValueError:
logger.warning(f"Неизвестное расширение файла: {file_type}")
return None
else:
ft = file_type
if ft is None:
logger.warning("Тип файла не указан при парсинге из объекта файла")
return None
# Получаем парсер для указанного типа файла
parsers = [p for p in self.factory.parsers if p.supports_file(ft)]
if not parsers:
logger.warning(f"Не найден подходящий парсер для типа файла: {ft}")
return None
# Используем первый подходящий парсер
parser = parsers[0]
# Парсим документ
try:
return parser.parse(file, ft)
except Exception as e:
logger.error(f"Ошибка при парсинге файла: {e}")
raise
|