こんにちは、挑戦するエンジニア のり ですよ。
みなさんは、文章データを扱うときに、単語単位に分割したいことってありませんか?
文から名詞だけを抜き出したいと考えていても、方法がわからないと大変ですよね。
今回はPythonのライブラリjanomeを使用して、日本語を単語単位に分割する方法を解説します。
始めに
この記事では、Pythonのプログラムで日本語を単語単位に分割する方法を解説します。
この記事を読んでいただくことで、日本語の文章データをPythonのプログラムで単語単位に分割する方法を知っていただくことが出来ます。
筆者の環境(Windows11 23H2、Python3.12、janome 0.5.0)での手順を紹介します。
また、janomeは無料で使うことが出来るプログラムです。
ぜひ、挑戦してみてください!
janomeのライセンスは「Apache License, Version 2.0」です。
[参考にしたサイト(その1)]
https://mocobeta.github.io/janome/
[参考にしたサイト(その2)]
https://mocobeta.github.io/janome/api/janome.html
[参考にしたサイト(その3)]
https://mocobeta.github.io/janome/api/_modules/janome/tokenizer.html
[参考にしたサイト(その4)]
https://github.com/mocobeta/janome/blob/master/janome/tokenizer.py
janomeで出来ること
janomeで出来ることは、日本語の文章データを単語単位に分割することです。
また、「形態素解析」という文から単語に分解し、品詞などを判別する処理を行うことができます。
形態素解析についてはこちらを参照
janomeは形態素解析(文から単語への分解、品詞の判別)を行うことが出来る。
それでは、janomeの使い方について見ていきたいと思います。
janomeの準備
janomeを使うには準備が必要です。
Pythonがインストールされている環境で次のコマンドを実行して、janomeをセットアップしていきます。
python -m pip install --upgrade pip
続いてjanomeをインストールします。
pip install janome
janomeがインストール出来たか、バージョン情報を表示して確認します。
janome --version
コンソールにバージョンの数字が表示されれば成功です。
janomeは、pipコマンドでインストールできる。
次は、janomeライブラリの使い方です。
janomeの使い方(形態素解析)
janomeを使った形態素解析を行うプログラムの例です。
"""
janomeを使って形態素解析(単語分割)
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#文の定義
sentence: str = "これは短い文の例です。"
#Tokenizerのインスタンスを取得
tk = Tokenizer()
#文を解析
tokens = tk.tokenize(sentence)
#解析結果の出力
for token in tokens:
print(token)
文の解析結果をtokensに取得して、単語ごとに要素(token)として取得することが出来ます。
要素(token)をprintした実行結果は次のようになります。
これ 名詞,代名詞,一般,*,*,*,これ,コレ,コレ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
短い 形容詞,自立,*,*,形容詞・アウオ段,基本形,短い,ミジカイ,ミジカイ
文 名詞,一般,*,*,*,*,文,ブン,ブン
の 助詞,連体化,*,*,*,*,の,ノ,ノ
例 名詞,一般,*,*,*,*,例,レイ,レイ
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。 記号,句点,*,*,*,*,。,。,。
単語単位に分割した、品詞や読み方などの情報を出力してくれます。
単語ごとに要素(token)として取得することが出来る。
また、要素(token)はひとつづつ項目を分解して取得することが出来ます。
先頭の単語のみ、項目ごとに出力するプログラムの例です。
"""
janomeを使って形態素解析(単語分割詳細表示)
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#文の定義
sentence: str = "これは短い文の例です。"
#Tokenizerのインスタンスを取得
tk = Tokenizer()
#文を解析
tokens = tk.tokenize(sentence)
#解析結果の出力
for token in tokens:
#余分に保持するデータ(タプル)
print(token.extra)
#単語の表記(表層形)
print(token.surface)
#単語の品詞
print(token.part_of_speech)
#単語の活用型
print(token.infl_type)
#単語の活用形
print(token.infl_form)
#活用の基本形
print(token.base_form)
#読み方
print(token.reading)
#発音記号(カナ表記)
print(token.phonetic)
#出典辞書の種類
print(token.node_type)
break
要素(token)はひとつづつ項目を分解して取得することが出来る。
タプルextraに持っている情報を、属性名を指定して取得することが出来ます。
実行結果は次のようになります。
('名詞,代名詞,一般,*', '*', '*', 'これ', 'コレ', 'コレ')
これ
名詞,代名詞,一般,*
*
*
これ
コレ
コレ
SYS_DICT
ただし、この属性の取得はドキュメントに記載がありません。
janomeのプログラムソースを見て記載していますので、使う際は慎重にお願いします。
属性名を指定して取得する場合、注意が必要。
次は、janome.Tokenizerを使った「分かち書き」の例です。
分かち書き
janomeを使った分かち書きを行うプログラムの例です。
"""
janomeを使って分かち書き
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#文の定義
sentence: str = "これは短い文の例です。"
#Tokenizerのインスタンスを取得
tk = Tokenizer()
#文を解析
tokens = tk.tokenize(sentence,wakati=True)
#解析結果の出力
for token in tokens:
print(token)
実行結果は次のようになります。
これ
は
短い
文
の
例
です
。
引数に渡した文の文字列を、単語単位に「分かち書き」してくれました。
janomeを使って、単語単位に「分かち書き」出来る。
次は、janome.Tokenizerとユーザー辞書を使った形態素解析の例です。
ユーザー辞書を使った形態素解析
janomeとユーザー辞書を使った形態素解析を行うプログラムの例です。
"""
janomeを使って形態素解析(ユーザー辞書付き単語分割)
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#文の定義
sentence: str = "あれはレインボーブリッジです。"
#Tokenizerのインスタンスを取得
tk = Tokenizer(udic='C:\\Python\\workspace\\user_dic.csv',udic_enc='utf8',udic_type="simpledic")
#文を解析
tokens = tk.tokenize(sentence)
#解析結果の出力
for token in tokens:
print(token)
ユーザー辞書は次のように準備しました。
レインボーブリッジ,カスタム名詞,レインボーブリッジ
実行結果は次のようになります。
あれ 名詞,代名詞,一般,*,*,*,あれ,アレ,アレ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
レインボーブリッジ カスタム名詞,*,*,*,*,*,レインボーブリッジ,レインボーブリッジ,レインボーブリッジ
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。 記号,句点,*,*,*,*,。,。,。
基本の辞書だけで実行すると、「レインボー」と「ブリッジ」に分割して解析されます。
ユーザー辞書を使った場合、「レインボーブリッジ」をカスタム名詞として解析してくれました。
ユーザー辞書を使うことで、単語の識別をカスタマイズすることが出来る。
次は、janomeを使うときの前処理についてです。
Analyzerフレームワークによる前処理
Analyzerフレームワークを使って、前処理を行うプログラムの例です。
charfilterを使います。
"""
janomeを使って形態素解析(Analyzerフレームワークによる前処理付き)
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#Analyzerのインポート
from janome.analyzer import Analyzer
#charfilter(UnicodeNormalizeCharFilter)のインポート
from janome.charfilter import UnicodeNormalizeCharFilter
#文の定義
sentence: str = "あれは、レインボーブリッジです。"
#charfilterの定義
char_filters: list = [UnicodeNormalizeCharFilter()]
#Tokenizerのインスタンスを取得
tokenizer = Tokenizer()
#文を解析
an = Analyzer(char_filters=char_filters, tokenizer=tokenizer)
#解析結果の出力
for token in an.analyze(sentence):
print(token)
実行結果は次のようになります。
あれ 名詞,代名詞,一般,*,*,*,あれ,アレ,アレ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
、 記号,読点,*,*,*,*,、,、,、
レインボー 名詞,一般,*,*,*,*,レインボー,レインボー,レインボー
ブリッジ 名詞,一般,*,*,*,*,ブリッジ,ブリッジ,ブリッジ
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。 記号,句点,*,*,*,*,。,。,。
前処理に指定したUnicodeNormalizeCharFilterのおかげで、半角カナの「レインボー」も全角カナの「レインボー」に変換されています。
charfilterには下記のクラスがあり、実行時に設定することで効率よく前処理を行うことが出来ます。
charfilterは設定された順に適用されるため、設定の順序が重要になります。
RegexReplaceCharFilter
正規表現にマッチした文字列を置き換えます。
UnicodeNormalizeCharFilter
ユニコード文字列の一般化を行います。
デフォルトの設定では、最初に互換性分解を適用し、続いて標準合成を適用します。
Analyzerフレームワークを使うと、解析前に処理が行える。
次は、janomeを使うときの後処理についてです。
Analyzerフレームワークによる後処理
Analyzerフレームワークを使って、後処理を行うプログラムの例です。
tokenfilterを使います。
"""
janomeを使って形態素解析(Analyzerフレームワークによる前処理付き)
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#Analyzerのインポート
from janome.analyzer import Analyzer
#charfilter(UnicodeNormalizeCharFilter)のインポート
from janome.charfilter import UnicodeNormalizeCharFilter
#tokenfilter(CompoundNounFilter)のインポート
from janome.tokenfilter import CompoundNounFilter
#tokenfilter(POSStopFilter)のインポート
from janome.tokenfilter import POSStopFilter
#文の定義
sentence: str = "あれは、レインボーブリッジです。"
#charfilterの定義
char_filters: list = [UnicodeNormalizeCharFilter()]
#Tokenizerのインスタンスを取得
tokenizer = Tokenizer()
#tokenfilterの定義
token_filters = [CompoundNounFilter(), POSStopFilter(['記号','助詞','助動詞'])]
#文を解析
an = Analyzer(char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters)
#解析結果の出力
for token in an.analyze(sentence):
print(token)
実行結果は次のようになります。
あれ 名詞,代名詞,一般,*,*,*,あれ,アレ,アレ
レインボーブリッジ 名詞,複合,*,*,*,*,レインボーブリッジ,レインボーブリッジ,レインボーブリッジ
後処理に指定したCompoundNounFilterのおかけで、「レインボーブリッジ」が複合名詞として認識されています。
また、POSStopFilterのおかげで、指定した品詞の単語は出力されなくなりました。
tokenfilterには下記のクラスがあり、実行時に設定することで効率よく後処理を行うことが出来ます。
tokenfilterは設定された順に適用されるため、設定の順序が重要になります。
CompoundNounFilter
複数の単語(token)から複合名詞を作成します。
引数はありません。
ExtractAttributeFilter
単語(token)の指定された属性を抽出します。
戻り値は単語(token)ではなく文字列であるため、このフィルターはトークンフィルターチェーンの最後に配置する必要があります。
引数は属性名(str)です。
LowerCaseFilter
単語(token)の表層形と基本形を小文字に変換します。
引数はありません。
UpperCaseFilter
単語(token)の表層形と基本形を大文字に変換します。
引数はありません。
POSKeepFilter
リストされている品詞の単語を保持し、それ以外の品詞の単語を削除します。
引数はlist形式のstrです。
POSStopFilter
リストされている品詞の単語を削除し、それ以外の品詞の単語を保持します。
引数はlist形式のstrです。
WordKeepFilter
単語の表層形がリストされている単語(token)を保持します。
引数はlist形式のstrです。
WordStopFilter
単語の表層形がリストされている単語(token)を削除します。
引数はlist形式のstrです。
Analyzerフレームワークを使うと、解析後に処理が行える。
次は、janomeを使った単語の出現数をカウントする方法です。
Analyzerフレームワークによる単語の出現数のカウント
Analyzerフレームワークを使って、単語の出現数のカウントを行うプログラムの例です。
tokenfilterのTokenCountFilterを使います。
"""
janomeを使って形態素解析(Analyzerフレームワークによる前処理付き)
"""
#Tokenizerのインポート
from janome.tokenizer import Tokenizer
#Analyzerのインポート
from janome.analyzer import Analyzer
#charfilter(UnicodeNormalizeCharFilter)のインポート
from janome.charfilter import UnicodeNormalizeCharFilter
#tokenfilter(POSKeepFilter)のインポート
from janome.tokenfilter import POSKeepFilter
#tokenfilter(TokenCountFilter)のインポート
from janome.tokenfilter import TokenCountFilter
#文の定義
sentence: str = "すもももモモもモモのうち"
#charfilterの定義
char_filters: list = [UnicodeNormalizeCharFilter()]
#Tokenizerのインスタンスを取得
tokenizer = Tokenizer()
#tokenfilterの定義
token_filters = [POSKeepFilter(['名詞']), TokenCountFilter()]
#文を解析
an = Analyzer(char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters)
#解析結果の出力
for token in an.analyze(sentence):
print(token)
実行結果は次のようになります。
('すもも', 1)
('モモ', 2)
('うち', 1)
TokenCountFilterの機能により、名詞の出現数をカウントできています。
TokenCountFilterの機能で、単語の出現数をカウントすることが出来る。
次は、janomeに関する豆知識です。
豆知識
janomeに関して知っておいた方がよいことを紹介します。
janomeはpure Python でコーディングされている!
janomeはpure Python でコーディングされているため、pipなどでライブラリさえ導入すれば面倒なインストール作業は不要です。
janomeはMeCabと同じ辞書を使用している!
janomeと同じような機能を持つライブラリに「MeCab」があります。
janomeはMeCabのデフォルトシステム辞書を使っているため、MeCabと同等の解析結果になるとのことです。
バグがなければとのことなので、バグがないことを祈ります!
janomeの処理速度について
janomeの処理速度は、同様の処理が可能なMeCabの約10倍時間がかかるそうです。
両者のメリットとデメリットは次の通りです。
janome | MeCab | |
セットアップ | pip(簡単) | インストール(面倒) |
処理速度 | 遅い | 早い |
バッチ処理などで大量に文を処理したい場合は、MeCabの導入を検討したほうが良いかもしれません。
ライブラリはjanome以外に、MeCabを利用する選択肢もある。
それでは、最後のまとめです。
まとめ
今回は、Pythonでjanomeを使って日本語を単語単位に分割する方法を解説しました。
日本語の文を「分かち書き」することで、いろいろな処理を構築出来るといいですね。
それでは、今日の解説はこのへんで。
またのお越しをお待ちしております。