Исходный код rupo.files.reader
# -*- coding: utf-8 -*-
# Автор: Гусев Илья
# Описание: Считыватель файлов разных расширений.
import os
import xml.etree.ElementTree as etree
import json
from enum import Enum
from typing import Iterator
from rupo.main.markup import Markup
from rupo.main.phonetics import Phonetics
from rupo.accents.dict import AccentDict
from rupo.accents.classifier import MLAccentClassifier
from rupo.metre.metre_classifier import MetreClassifier
RAW_SEPARATOR = "\n\n\n"
[документация]class FileTypeEnum(Enum):
"""
Тип файла.
"""
RAW = ".txt"
XML = ".xml"
JSON = ".json"
STIHI = ""
[документация]class Reader(object):
"""
Считывание из файлов.
"""
@staticmethod
[документация] def read_markups(path: str, source_type: FileTypeEnum, is_processed: bool,
accents_dict: AccentDict=None, accents_classifier: MLAccentClassifier=None) -> Iterator[Markup]:
"""
Считывание разметок (включая разметку по сырым текстам).
:param path: путь к файлу/папке.
:param source_type: тип файлов.
:param is_processed: уже размеченные тексты?
:param accents_dict: словарь ударений (для неразмеченных текстов).
:param accents_classifier: классификатор ударений (для неразмеченных текстов).
"""
paths = Reader.__get_paths(path, source_type.value)
for filename in paths:
with open(filename, "r", encoding="utf-8") as file:
if is_processed:
if source_type == FileTypeEnum.XML:
for elem in Reader.__xml_iter(file, 'markup'):
markup = Markup()
markup.from_xml(etree.tostring(elem, encoding='utf-8', method='xml'))
yield markup
elif source_type == FileTypeEnum.JSON:
j = json.load(file)
for item in j['items']:
markup = Markup()
markup.from_dict(item)
yield markup
elif source_type == FileTypeEnum.RAW:
raise NotImplementedError("Пока не реализовано.")
else:
assert accents_dict is not None
assert accents_classifier is not None
for text in Reader.read_texts(filename, source_type):
yield Reader.__markup_text(text, accents_dict, accents_classifier)
@staticmethod
[документация] def read_texts(path: str, source_type: FileTypeEnum) -> Iterator[str]:
"""
Считывание текстов.
:param path: путь к файлу/папке.
:param source_type: тип файлов.
"""
paths = Reader.__get_paths(path, source_type.value)
for filename in paths:
with open(filename, "r", encoding="utf-8") as file:
if source_type == FileTypeEnum.XML:
for elem in Reader.__xml_iter(file, 'item'):
yield elem.find(".//text").text
elif source_type == FileTypeEnum.JSON:
# TODO: ленивый парсинг
j = json.load(file)
for item in j['items']:
yield item['text']
elif source_type == FileTypeEnum.RAW:
text = file.read()
for t in text.split(RAW_SEPARATOR):
yield t
elif source_type == FileTypeEnum.STIHI:
text = ""
is_text = False
for line in file:
if "<div" in line:
is_text = True
elif "</div>" in line:
is_text = False
yield text
elif is_text:
text += line + "\n"
@staticmethod
def __get_paths(path: str, ext: str) -> Iterator[str]:
"""
Получение всех файлов заданного типа по заданному пути.
:param path: путь к файлу/папке.
:param ext: требуемое расширение.
"""
if os.path.isfile(path):
if ext == os.path.splitext(path)[1]:
yield path
else:
for root, folders, files in os.walk(path):
for file in files:
if ext == os.path.splitext(file)[1]:
yield os.path.join(root, file)
for folder in folders:
return Reader.__get_paths(folder, ext)
@staticmethod
def __markup_text(text: str, accents_dict: AccentDict=None,
accents_classifier: MLAccentClassifier=None) -> Markup:
"""
Разметка текста.
:param text: текст.
:param accents_dict: словарь ударений.
:param accents_classifier: классификатор ударений.
:return: разметка.
"""
markup = Phonetics.process_text(text, accents_dict)
markup = MetreClassifier.improve_markup(markup, accents_classifier)[0]
return markup
@staticmethod
def __xml_iter(file, tag):
"""
:param file: xml файл.
:param tag: заданный тег.
:return: все элементы с заданными тегами в xml.
"""
return (elem for event, elem in etree.iterparse(file, events=['end']) if event == 'end' and elem.tag == tag)