Créez un outil qui secoue automatiquement furigana avec html en utilisant Mecab de Python3

2019.3.25 post-scriptum

Le programme présenté dans cet article peut gérer les exemples de phrases décrits dans une certaine mesure, mais j'ai constaté que certains mots ne se balançaient pas correctement.

Le site suivant présente une meilleure version du code de cet article, alors jetez un œil! https://www.karelie.net/python3-mecab-html-furigana-1/

Nous remercions Kimera d'avoir signalé les problèmes dans cet article.

Ce que tu peux faire

Je veux quitter l'université

Automatiquement quand il y a du HTML

<ruby><rb>je</rb><rt>je</rt></ruby>Est
<ruby><rb>Université</rb><rt>Génial</rt></ruby>À
<ruby><rb>Démission</rb><rt>Ou</rt></ruby>Metai

I </ rb> I </ rt> </ ruby> Université </ rb> Daigaku </ rt> </ ruby> Remarques </ rb> et </ rt> </ ruby>

Et le rubis viendra toucher

Les choses nécessaires

L'environnement est MacOS et la version Python est 3.5.1. 1.Mecab (dans mon cas, il était inclus dans mac par défaut, je vais donc l'omettre) 2.mecab-python3 3.pip (requis pour installer mecab-python3)

Obtenez ce dont vous avez besoin

Mecab est un outil d'analyse de dictionnaire qui vous permet d'obtenir la lecture des kanji en l'utilisant.

Vous pouvez l'exécuter / l'obtenir en exécutant la commande mecab à partir de la ligne de commande et en entrant du texte sur la ligne suivante.

$ mecab
Je veux quitter l'université
Mon nom,Synonyme,Général,*,*,*,je,je,je
Est un assistant,Assistance,*,*,*,*,Est,C,sensationnel
Nomenclature universitaire,Général,*,*,*,*,Université,Daigaku,Daigaku
Auxiliaire,Assistant de cas,Général,*,*,*,À,Wo,Wo
Quitter le verbe,Indépendance,*,*,Un pas,Type continu,Quitter,Yame,Yame
Verbe assistant Tai,*,*,*,Spécial Thaïlande,Forme basique,Vouloir,Thaïlande,Thaïlande
EOS

Afin de gérer ce Mecab avec python3, un package appelé python-mecab3 est requis.

Parce que l'outil pour gérer ces packages s'appelle pip Si pip n'est pas installé, installez-le d'abord. (Semblable à un bijou en rubis)

installation de pip

$ easy_install pip

Au fait, il semble qu'il soit inclus par défaut depuis python3.4.

installer mecab-python3

Après avoir installé pip, installez mecab-python3.

$ pip install mecab-python3

Vous pouvez obtenir une liste des packages actuellement inclus avec la commande pip list. Si vous avez mecab-python, l'installation est réussie.

$ pip list
mecab-python3 (0.7)

Traitons Mecab avec python3 pour le moment

Maintenant que l'environnement est prêt pour le moment, essayons d'utiliser mecab de python et voyons comment nous pouvons obtenir les données.

macab.py


#!/usr/local/src/pyenv/shims/python
# -*- coding: utf_8 -*-
import sys
import MeCab

mecab = MeCab.Tagger("-Ochasen")#Appeler Mecab
text=mecab.parse('Je veux quitter l'université')#Obtenez Furigana

print(text)
$ mecab.py
Je suis ma nomenclature-Synonyme-Général
Ha ha est un assistant-Assistance
Université Daigaku University Noun-Général
Wo wo auxiliaire-Assistant de cas-Général
Quitter verbe-Type d'utilisation continue à un étage indépendant
Tai Tai Tai Tai Verbe auxiliaire spécial / forme de base thaï
EOS

Parse semble vouloir dire "analyse"

mecab = MeCab.Tagger("-Ochasen")

Après avoir appelé Mecab avec

text=mecab.parse('Je veux quitter l'université')

Vous pouvez l'obtenir au format comme le résultat de l'exécution en appelant la méthode d'analyse et en spécifiant le texte que vous souhaitez analyser dans l'argument.

Utilisez parseToNode

J'ai pu l'obtenir pour le moment, mais ce format est très difficile à gérer par programmation car il est séparé par des espaces.

Par conséquent, changez-le en un format appelé Node pour le rendre plus facile à gérer.

mecab.py


import sys
import MeCab


mecab = MeCab.Tagger("-Ochasen")
mecab.parse('')#Besoin d'analyser dans le ciel
node=mecab.parseToNode('Je veux quitter l'université')

while node :
    print(node.surface+"\t"+node.feature)
    node=node.next
$ mecab.py
	BOS/EOS,*,*,*,*,*,*,*,*
Mon nom,Synonyme,Général,*,*,*,je,je,je
Est un assistant,Assistance,*,*,*,*,Est,C,sensationnel
Nomenclature universitaire,Général,*,*,*,*,Université,Daigaku,Daigaku
Auxiliaire,Assistant de cas,Général,*,*,*,À,Wo,Wo
Quitter le verbe,Indépendance,*,*,Un pas,Type continu,Quitter,Yame,Yame
Verbe assistant Tai,*,*,*,Spécial Thaïlande,Forme basique,Vouloir,Thaïlande,Thaïlande
	BOS/EOS,*,*,*,*,*,*,*,*

Cela facilite la manipulation car les résultats de l'analyse peuvent être obtenus séparés par ",".

Comme auparavant, lorsque vous appelez mecab, il semble que vous deviez vider l'argument et l'analyser pour le moment, alors faites-le.

ensuite

node=mecab.parseToNode('Je veux quitter l'université')

Spécifiez une phrase dans l'argument de la méthode parseToNode.

Puisque le nœud est traité mot par mot, utilisez l'instruction while. Boucle jusqu'à la fin de la phrase (fin de la valeur dans node).

Dans la boucle Le texte de l'argument d'origine dans node.surface, Vous pouvez obtenir des données d'analyse séparées par des virgules avec node.feature.

Au fait

  node=node.next

Si vous oubliez, il bouclera indéfiniment, alors faites attention.

Jusqu'à présent, j'ai réussi à utiliser mecab de python pour le moment.

En fait, secouez le rubis au format HTML

Jusqu'à présent, il y avait beaucoup d'informations sur Internet, À partir de maintenant, il n'y a pas beaucoup d'informations et c'est une partie difficile.

Cependant, il s'agit essentiellement d'un travail à appliquer au html tout en jouant avec la fonction node.feature ci-dessus.

Comment balancer le rubis en HTML

<ruby><rb>lettre</rb><rt>Moji</rt></ruby>

caractères </ rb> moji </ rt> </ ruby>

Parce que ce sera sous la forme de Appliquons le kanji d'origine dans la balise et le furigana dans la balise rt.

mecab.py


#!/usr/local/src/pyenv/shims/python
# -*- coding: utf_8 -*-

import sys
import MeCab
import re

mecab = MeCab.Tagger("-Ochasen")
mecab.parse('')#Besoin d'analyser dans le ciel
node=mecab.parseToNode('Je veux quitter l'université')

while node :
    origin=node.surface#Remplacez le mot d'origine
    kana=node.feature.split(",")[7]#Lecture de substitution kana

    #Vérifiez si l'expression régulière correspond aux kanji
    pattern = "[un-龥]"
    matchOB = re.match(pattern , origin)

    #Lorsque l'origine est vide, il n'est pas nécessaire de secouer le furigana quand ce n'est pas un kanji, il est donc sorti tel quel
    if origin != "" and matchOB:
        print("<ruby><rb>{0}</rb><rt>{1}</rt></ruby>".format(origin,kana),end="")
    else :
        print(origin)

    node=node.next

$ mecab.py
<ruby><rb>je</rb><rt>je</rt></ruby>Est
<ruby><rb>Université</rb><rt>Daigaku</rt></ruby>À
<ruby><rb>Quitter</rb><rt>Yame</rt></ruby>Vouloir

I </ rb> I </ rt> </ ruby> Université </ rb> Daigaku </ rt> </ ruby> ruby> Quitter </ rb> Yame </ rt> </ ruby>

Ça devient de plus en plus comme ça.

Tout d'abord, dans les deux premières lignes, attribuez des mots et des lectures à l'origine et au kana, respectivement.

En ce qui concerne le yomigana, puisque le yomigana est le 7ème noeud séparé par des virgules. La fonction de division spécifie le 7ème tableau séparé par des virgules.

origin=node.surface #Remplacez le mot d'origine
kana=node.feature.split(",")[7] #Lecture de substitution kana

Ensuite, cette fois, je veux faire semblant d'être Furigana uniquement lorsque le mot original est Kanji. Utilisez des expressions régulières pour vérifier si le mot d'origine est un kanji.

Pour utiliser une expression régulière, importez d'abord au début.

import re

Je n'entrerai pas dans les détails sur les expressions régulières ici, Il existe différentes méthodes pour réimporter plus tôt.

Cette fois, je veux savoir si le premier caractère du mot origine est un kanji Utilisez la méthode de correspondance. Spécifiez un modèle (Kanji cette fois) dans le premier argument et un mot dans le deuxième argument.

En cas de correspondance, les informations sur la correspondance, appelées objet de correspondance, sont stockées. S'il n'y a pas de correspondance, "Aucun" est stocké.

  #Vérifiez si l'expression régulière correspond aux kanji
    pattern = "[un-龥]" #Motif Kanji
    matchOB = re.match(pattern , origin) #Aucun quand il n'est pas en kanji

Enfin, si est utilisé pour le jugement.

Si vous l'organisez en japonais ・ Lorsque l'origine est kanji ➡ Secouez ruby avec html et sortie ・ Lorsque l'origine est autre que Kanji (Hiragana, Katakana, Nombre, etc.) ➡ Sortie telle quelle Ce sera.

  #Lorsque l'origine est vide, il n'est pas nécessaire de secouer le furigana quand ce n'est pas un kanji, il est donc sorti tel quel
    if matchOB and origin != "" :
        print("<ruby><rb>{0}</rb><rt>{1}</rt></ruby>".format(origin,kana),end="")
    else :
        print(origin)

Lorsque l'origine est autre que Kanji, None est assigné à marchOB, il sera donc jugé et se déplacera vers else.

Jusque-là, c'est devenu tout à fait une forme, mais il y a un problème.

Problème de Katakana

Je veux faire basculer le kana d'envoi avec hiragana, mais le kana de lecture qui peut être obtenu avec Mecab est katakana, donc je veux le convertir en hiragana.

Dans Ruby, vous pouvez le faire d'un seul coup en utilisant une fonction, mais pour autant que j'ai vérifié avec Python, il semble que cela ne puisse pas être fait.

Par conséquent, je vais concevoir quelque chose ici.

Tout d'abord, préparez un tableau de ces caractères hiragana et katakana un par un.

hiragana=["Ah","je","U","Hmm"]#hiragana[0]=="Ah"
katakana=["UNE,"je","C","Vers le bas"]#katakana[0]=="UNE"

Et par exemple Supposons que vous vouliez changer le mot «ai» en «ai».

text=list("Œil")#text[0]=="UNE" text[1]=="je"devenir
kana=""#Variable pour mettre hiragana

for hoge in len(text)#Répétez pour le nombre de caractères(Substitut pour hoge)
  for i in list(katakana)
    katakana[i]==hoge
    kana+=hiragana[i]

print(kana)#Ai

Je veux diviser "Ai" en A et I et les assembler un par un. Divisez le caractère «œil» par caractère dans un tableau.

Ensuite, bouclez le numéro du tableau (= nombre de caractères).

Dans celui-ci, bouclez par le nombre de katakana et faites correspondre avec hoge. Puisque le contenu du hoge de la première boucle cette fois est "A" Quand i vaut 0, cela correspond à katakana [0].

Enfin, hiragana [i], c'est-à-dire hiragana [0], c'est-à-dire "a" Vers la variable kana.

Si vous répétez ceci pour le nombre de caractères, kana aura hiragana.

Voici le code qui modularise cela.

mecab.py


#!/usr/local/src/pyenv/shims/python
# -*- coding: utf_8 -*-

import sys
import MeCab
import re

def henkan(text) :
    hiragana=[chr(i) for i in range(12353, 12436)]
    katakana=[chr(i) for i in range(12449, 12532)]
    kana=""
    #Hiragana avec Kata Kana de Yomikana
    for text in list(text):
        for i in range(83):
            if text == katakana[i]:
                kana+=hiragana[i]
    return kana

mecab = MeCab.Tagger("-Ochasen")
mecab.parse('')#Besoin d'analyser dans le ciel
node=mecab.parseToNode('Je veux quitter l'université')

while node :
    origin=node.surface#Remplacez le mot d'origine
    kana=node.feature.split(",")[7]#Lecture de substitution kana
    kana=henkan(kana)#Appelez la fonction de conversion et transformez le katakana en hiragana

    #Vérifiez si l'expression régulière correspond aux kanji
    pattern = "[un-龥]"
    matchOB = re.match(pattern , origin)

    #Lorsque l'origine est vide, il n'est pas nécessaire de secouer le furigana quand ce n'est pas un kanji, il est donc sorti tel quel
    if origin != "" and matchOB:
        print("<ruby><rb>{0}</rb><rt>{1}</rt></ruby>".format(origin,kana),end="")
      
    else :
        print(origin)

    node=node.next

Je vais omettre les détails,

range(83)

En effet, le nombre d'arrangements est de 83 ainsi que 50 sons avec l'ajout de minuscules.

Problème d'envoi de pseudonyme

Un autre problème est le problème de l'envoi de pseudonymes. Puisque Mecab est séparé pour chaque mot, il inclut également le pseudonyme d'envoi, ce qui signifie que le rubis n'est pas purement attribué aux kanji.

En d'autres termes

<ruby><rb>Quitter</rb><rt>Arrêtez</rt></ruby>

Quitter </ rb> Arrêter </ rt> </ ruby>

ne pas

<ruby><rb>Démission</rb><rt>Ou</rt></ruby>Moi

Remarques </ rb> et </ rt> </ ruby>

Je veux le faire.

Jetons un coup d'oeil à ceci.

Fondamentalement, il détermine si le mot d'origine et la fin du pseudonyme d'envoi correspondent.

origine: beauté bonne </ font> kana: Utsukushi Shii </ font> origine: exécuter exécuter </ font> kana: baguettes ru </ font>

Comme ceux-ci ont les mêmes deux ou une lettre à la fin, ils peuvent être considérés comme envoyant des pseudonymes.

Sur ce point également, comme dans le cas du problème Katakana plus tôt Décomposer l'origine et le caractère kana par caractère et les organiser Juge si un ou deux caractères à la fin d'une correspondance de mots.

mecab.py


#!/usr/local/src/pyenv/shims/python
# -*- coding: utf_8 -*-

import sys
import MeCab
import re

def henkan(text) :
    hiragana=[chr(i) for i in range(12353, 12436)]
    katakana=[chr(i) for i in range(12449, 12532)]
    kana=""
    #Hiragana avec Kata Kana de Yomikana
    for text in list(text):
        for i in range(83):
            if text == katakana[i]:
                kana+=hiragana[i]
    return kana


mecab = MeCab.Tagger("-Ochasen")
mecab.parse('')#Besoin d'analyser dans le ciel
node=mecab.parseToNode('Je veux quitter l'université')

while node :
    origin=node.surface#Remplacez le mot d'origine
    yomi=node.feature.split(",")[7]#Lecture de substitution kana
    kana=henkan(yomi)

    #Vérifiez si l'expression régulière correspond aux kanji
    pattern = "[un-龥]"
    matchOB = re.match(pattern , origin)

    #Lorsque l'origine est vide, il n'est pas nécessaire de secouer le furigana quand ce n'est pas un kanji, il est donc sorti tel quel
    if origin != "" and matchOB:

        origin=list(origin)
        kana=list(kana)
        num1=len(origin)
        num2=len(kana)
        okurigana=""

        if origin[num1-1] == kana[num2-1] and origin[num1-2] == kana[num2-2] :
            okurigana=origin[num1-2]+origin[num1-1]

            origin[num1-1]=""
            origin[num1-2]=""
           kana[num2-1]=""
           kana[num2-2]=""

            origin="".join(origin)
            kana="".join(kana)

        elif origin[num1-1] == kana[num2-1] :

            okurigana=origin[num1-1]

            origin[num1-1]=""
            kana[num2-1]=""

            origin="".join(origin)
            kana="".join(kana)

        else :
            origin="".join(origin)
            kana="".join(kana)

        print("<ruby><rb>{0}</rb><rt>{1}</rt></ruby>".format(origin,kana),end="")
        print(okurigana)

    else :
        print(origin)

    node=node.next

Quand tu fais ça,

$ mecab.py
<ruby><rb>je</rb><rt>je</rt></ruby>
Est
<ruby><rb>Université</rb><rt>Génial</rt></ruby>
À
<ruby><rb>Démission</rb><rt>Ou</rt></ruby>Moi
Vouloir

I </ rb> I </ rt> </ ruby> Université </ rb> Daigaku </ rt> </ ruby> Remarques </ rb> et </ rt> </ ruby>

Et c'est terminé! !! !!

Regardons de plus près.

origin=list(origin)
kana=list(kana)

num1=len(origin)
num2=len(kana)
 
okurigana=""

Tout d'abord, comme je l'ai mentionné plus tôt, j'ai vérifié chaque caractère, je vais donc les organiser avec la fonction de liste.

Aussi, pour vérifier si les fins correspondent, vérifiez le nombre de tableaux avec la fonction len. Remplacez respectivement num1 et num2.

  if origin[num1-1] == kana[num2-1] and origin[num1-2] == kana[num2-2] :
            okurigana=origin[num1-2]+origin[num1-1]

            origin[num1-1]=""
            kana[num1-2]=""
            origin[num2-1]=""
            kana[num2-2]=""

            origin="".join(origin)
            kana="".join(kana)

Il s'agit du traitement lorsque le dernier caractère et l'avant-dernier correspondent, c'est-à-dire C'est le processus pour des mots comme «beau».

Dans ce cas, les deux derniers caractères "shii" seront le pseudonyme d'envoi, donc Attribuez-le à la variable okurigana.

okurigana=origin[num1-2]+origin[num1-1]

Une fois que vous l'avez mis dans une variable, vous n'avez pas besoin de "Shii", alors supprimez-le.

origin[num1-1]=""
kana[num1-2]=""
origin[num2-1]=""
kana[num2-2]=""

Enfin à gauche origin = ["Beauté"] kana = ["u", "tsu", "ku"] Utilisez la fonction de jointure pour revenir à une variable.

origin="".join(origin)
kana="".join(kana)

Pour le reste, c'est peut-être un pseudonyme d'envoi d'une lettre comme "courir" C'est un processus lorsqu'il n'y a pas de pseudonyme d'envoi comme "université"

        elif origin[num1-1] == kana[num2-1] :
            okurigana=origin[num1-1]

            origin[num1-1]=""
            kana[num2-1]=""

            origin="".join(origin)
            kana="".join(kana)

        else :
            origin="".join(origin)
            kana="".join(kana)

Depuis qu'il a été arrangé, même s'il n'y a pas de traitement et qu'il n'y a pas de pseudonyme d'envoi Travaillez pour revenir à une variable.

Le dernier est la sortie.

Puisqu'il a été assigné à la variable exactement dans le traitement jusqu'à présent, il n'y a pas de changement spécial, mais puisque le pseudonyme d'envoi est assigné à okurigana, il n'y a rien de mal à ne pas oublier de le sortir.

print("<ruby><rb>{0}</rb><rt>{1}</rt></ruby>".format(origin,kana),end="")
print(okurigana)

Le reste est un peu difficile à voir s'il est laissé tel quel, donc si vous en faites une fonction, il sera terminé!

mecab.py


#!/usr/local/src/pyenv/shims/python
# -*- coding: utf_8 -*-

import sys
import MeCab
import re

def henkan(text) :
    hiragana=[chr(i) for i in range(12353, 12436)]
    katakana=[chr(i) for i in range(12449, 12532)]
    kana=""
    #Hiragana avec Kata Kana de Yomikana
    for text in list(text):
        for i in range(83):
            if text == katakana[i]:
                kana+=hiragana[i]
    return kana


def tohensu(origin,kana) :
    origin="".join(origin)
    kana="".join(kana)
    return origin,kana

def kanadelete(origin,kana) :
    origin=list(origin)
    kana=list(kana)
    num1=len(origin)
    num2=len(kana)
    okurigana=""

    if origin[num1-1] == kana[num2-1] and origin[num1-2] == kana[num2-2] :
        okurigana=origin[num1-2]+origin[num1-1]
        origin[num1-1]=""
        origin[num1-2]=""
        kana[num2-1]=""
        kana[num2-2]=""
        origin,kana=tohensu(origin,kana)

    elif origin[num1-1] == kana[num2-1] :

        okurigana=origin[num1-1]

        origin[num1-1]=""
        kana[num2-1]=""
        origin="".join(origin)
        kana="".join(kana)
    else :
        origin,kana=tohensu(origin,kana)

    return origin,kana,okurigana

mecab = MeCab.Tagger("-Ochasen")
mecab.parse('')#Besoin d'analyser dans le ciel
node=mecab.parseToNode("Je veux quitter l'université")

while node :
    origin=node.surface#Remplacez le mot d'origine
    yomi=node.feature.split(",")[7]#Lecture de substitution kana
    kana=henkan(yomi)

    #Vérifiez si l'expression régulière correspond aux kanji
    pattern = "[un-龥]"
    matchOB = re.match(pattern , origin)

    #Lorsque l'origine est vide, il n'est pas nécessaire de secouer le furigana quand ce n'est pas un kanji, il est donc sorti tel quel
    if origin != "" and matchOB:
        origin,kana,okurigana=kanadelete(origin,kana)
        print("<ruby><rb>{0}</rb><rt>{1}</rt></ruby>".format(origin,kana),end="")
        print(okurigana)
    else :
        print(origin)

    node=node.next

Recommended Posts