Рубрики
Без рубрики

Проект анализа текста Python: вставка Furigana для ANKI

Furigana Furigana – это японская помощь в чтении для Кандзи, которая первоначально приходила из китайца …. Tagged with Python, учебник, Showdev.

Фуригана

Фуригана – японская помощь в чтении для Кандзи, которая первоначально приходила из китайца.

Есть много Реализации, подобные этому Для вставки Фуриганы в японский текст в Интернет с помощью форматирования Ruby, но в этом посте мы рассмотрим формат ANKI.

Формат Фуриганы Анки

Формат Фуриганы Анки более читабелен и короче, что облегчает редактирование, а также экономит дисковое пространство. Он используется на ANKI, но довольно просто преобразовать его в формат Ruby для Интернета.

Вот примеры для めたい и 辿 たど :

Рубин формат: めたい Формат ANKI: 辞 [や] めたい

Рубин формат: 辿 たど Формат ANKI: 辿 [たど] り 着 [つ] く

В настоящее время двумя преобладающими инструментами для вставки Furigana в ANKI являются Японская поддержка аддон и Мигаку Японский добавить.

Однако есть некоторые проблемы с этими инструментами, так как они терпят неудачу по одной или нескольким из этих проблем.

  1. Хирагана посреди слова
  2. Специальные японские иероглифы и диапазон знаков препинания
  3. Пользовательский отображение для конкретных слов с несколькими показаниями, а также именами и местами.

Мы рассмотрим эти проблемы в этом проекте.

Судачи для сегментации текста

Текстовая сегментация – это метод разбить предложение на более мелкие куски, называемые морфемы Анкет Это позволит нам искать индивидуальные показания каждой морфемы и при необходимости применить чтение Фуриганы.

Вместо Mecab для общего сегментации, этот проект будет использовать Судачи , который имеет несколько режимов сегментации текста, а также поиск Furigana.

Мы также будем использовать Ванакана Пакет для Python Для основных японских текстовых манипуляций.

pip install sudachipy sudachidict_small wanakana-python

Режимы сегментации Судачи

Есть три режима сегментации в Судачи – A, B и C.

Мы будем использовать режим C, чтобы получить чтение самых длинных записей в предложении.

from sudachipy import tokenizer
from sudachipy import dictionary

tokenizer_obj = dictionary.Dictionary(dict_type="small").create()

def add_furigana(text):
    tokens = [m for m in tokenizer_obj.tokenize(text, tokenizer.Tokenizer.SplitMode.C)]
    parsed = ''
    # ...
    return parsed

Пропустить пунктуацию и специальные персонажи

Нам также необходимо определить определенных не японских персонажей (но считается японскими символами библиотекой Ванаканы:

from wanakana import to_hiragana, is_japanese, is_katakana, is_hiragana
import string

JAPANESE_PUNCTUATION = ' 〜!?。、():「」『』0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

def is_japanese_extended(text):
    return is_japanese(text) and text not in string.punctuation and text not in JAPANESE_PUNCTUATION

Затем мы можем добавить логику в наш метод вставки Фуригана. to_parse это только Истинный Если (морфем) токен содержит японские персонажи с кандзи. Другими словами, это ЛОЖЬ Если текст является чисто Хирагана или Катакана.

Специальные персонажи, такие как должны быть выделены, так как они привязаны к жетонам в Судачи.

SPECIAL_CHARACTERS = '〜'

def add_furigana(text):
    tokens = [m for m in tokenizer_obj.tokenize(text, tokenizer.Tokenizer.SplitMode.C)]
    parsed = ''
    for index, token in enumerate(tokens):   
        to_parse = is_japanese_extended(token.surface()) and not is_katakana(token.surface()) and not is_hiragana(token.surface())
        if to_parse:
            if token.surface()[-1] in SPECIAL_CHARACTERS:
                parsed += add_furigana(token.surface()[:-1]) + token.surface()[-1]
            else:
                if index > 0:
                    parsed += ' '
                  reading = to_hiragana(token.reading_form())
                # ...
         else:
             parsed += token.surface()
     return parsed

Есть несколько методов в токеновом элементе. Мы используем метод Surface () для получения исходной строки, и Reading_form (), чтобы получить чтение Furigana Morpheme.

Важным примечанием является то, что метод Reading_form () возвращает чтение в Катакане, которое необходимо преобразовать в Хирагану и может быть достигнут с помощью Ванаканы to_hiragana () метод

Пользовательское отображение и анализ

Мы можем создать небольшой словарь, чтобы отобразить индивидуальные элементы, которые мы хотим выполнить собственное отображение. Это может быть все, от использования более распространенных показаний ( Возвращает чтение わたく し вместо わたし ) к именам, как 優 那 [ゆう な] который неверно анализирует Судачи по 優 [ゆう] 那 [].

KANJI_READING_MAPPING = {
    '私': '私[わたし]',
    '貴女': '貴女[あなた]',
    '何が': '何[なに]が',
    '何を': '何[なに]を',
    '我国': '我国[わがくに]',
    '行き来': '行[い]き 来[き]',
    '外宇宙': '外宇宙[がいうちゅう]',
    '異星人': '異星人[いせいじん]',
    '優那': '優那[ゆうな]',
    '菜々美': '菜々美[ななみ]'
}

Мы также можем использовать Json Файл для более легкого управления данными, но здесь мы будем хранить его в файле Python.

Чтобы отобразить их вручную, проверяем, если их поверхность Форма является одним из ключей нашего Kanji_reading_mapping и добавить соответствующее значение к нашему проанализированному результату.

Иногда ключевое слово может охватывать 2 токены, например, 異星人 разбиваются на токены 異星 [いせい] и 人 [にん] и 優 那 в токены 優 [ゆう] и 那 []. Вот почему мы также проверяем, есть ли комбинированный термин текущего токена и следующий токен token.surface () + tokens [index + 1] .surface () Также являются ключом в нашем картирующем словаре.

token_indexes_to_skip = []
for index, token in enumerate(tokens): 
    if index in token_indexes_to_skip:
        continue
    # ...
    if index < len(tokens)-1 and token.surface() + tokens[index+1].surface() in KANJI_READING_MAPPING:
        parsed += KANJI_READING_MAPPING[tokens[index].surface() + tokens[index+1].surface()]
        token_indexes_to_skip.append(index+1)
    elif token.surface() in KANJI_READING_MAPPING:
        parsed += KANJI_READING_MAPPING[token.surface()]
    else:
    # ...

Добавляем список token_indexes_to_skip хранить Индекс+1 токены, которые уже используются для пользовательского картирования. Таким образом, мы можем пропустить его в следующей итерации.

Хирагана посреди слова

Мы устанавливаем два указателя , Surface_index Пройти через каждого персонажа Поверхностная форма и Reading_index Для * Чтение Анкет

Например, поверхностная форма 教える имеет форму считывания オシエル и впоследствии おしえる после преобразования Хирагана.

Если персонажем является Хирагана или Катакана, мы напрямую добавляем его в проанализированную строку и увеличиваем оба указателя.

Если это кандзи, мы находим чтение для кандзи, используя временную переменную Reading_index_tail и увеличьте это, пока мы не достигнем конца строки считывания или до тех пор, пока следующий символ чтения не соответствует следующему символу Hiragana в поверхностной строке.

Сопоставлением в おし る до 教 る Мы можем проанализировать чтение 教 до おし. Reading_index Значение 0 и Reading_index_tail Значение 1

Мы также добавим дополнительное условие, чтобы переместить указатель считывания, если последующий символ Хирагана совпадает с текущим.

Например, 可愛い анализируется как 可愛 [かわい] い вместо 可愛 [かわ] いい. Проверив повторение финального い, мы могли бы заставить первого い быть включенным в чтение.

surface_index = 0
reading_index = 0
while len(token.surface()) > surface_index:
    if is_hiragana(token.surface()[surface_index]) or is_katakana(token.surface()[surface_index]):
        parsed += token.surface()[surface_index]
        reading_index += 1
        surface_index += 1
    else:
        next_index = -1
        for token_index in range(surface_index, len(token.surface())):
            if is_hiragana(token.surface()[token_index]) or is_katakana(token.surface()[token_index]):
                next_index = token_index
                break
            if next_index < 0:
                parsed += to_anki_format(
index=surface_index, kanji=token.surface()[surface_index:], 
    reading=reading[reading_index:])
                break
            else:
                reading_index_tail = reading_index
                while reading[reading_index_tail] != token.surface()[next_index] or (reading_index_tail < len(reading)-1 and reading[reading_index_tail] == reading[reading_index_tail+1]):
                    reading_index_tail += 1
                parsed += to_anki_format(
                                  index = surface_index, 
                                  kanji = token.surface()[surface_index:next_index], 
                                  reading = reading[reading_index:reading_index_tail])
                reading_index = reading_index_tail
            reading_length = next_index - surface_index
            if reading_length > 0:
                surface_index += reading_length
            else:
                break

Формат Анки

Формат ANKI довольно прост. Вначале мы добавляем дополнительное пространство, если проанализированный кандзи находится в середине предложения.

def to_anki_format(index, kanji, reading):
    return '{}{}[{}]'.format(' ' if index > 0 else '', kanji, reading) 

Собрать это вместе

Было намного больше шагов и условной проверки, но в конце концов наш анализатор мог бы справиться с гораздо большим количеством случаев и быть очень настраиваемым.

Примечание. Чтобы запустить этот пример, вам может потребоваться запустить PIP установить SUDACHIDICT_SMALL в оболочке реплики, чтобы установить словарь Судачи.

Дополнительный

Анки

До сих пор мы рассмотрели, как добавить Furigana к японскому тексту в формате ANKI, но мы не рассмотрели, как сделать аддон ANKI (плагин). Это может быть простой управление горячими классами, чтобы преобразовать поле в японское с Фуриганой, или это может быть аддон для пакетной вставки Furigana в существующую колоду ANKI. Мы оставим это на другой пост.

Веб –

Предположим, что у вас есть реляционная база данных японского текста, и вы добавили дополнительный столбец для хранения всего текста с вставленной Furigana. Вам нужно будет получить данные и показать их в Интернете в формате Ruby.

Вам нужно будет написать простую функцию форматирования текста. Нет необходимости в библиотеках сегментации здесь. Вы можете взглянуть на мой Реагировать реализацию JS Если вам нужна помощь.

Оригинал: “https://dev.to/mathewthe2/python-text-parsing-project-furigana-inserter-for-anki-2jo”