powershell でも NEologd で形態素解析して読み仮名を取得したい（Python 経由で janome を呼び出す）

書籍の索引作成などでテキストデータの読み仮名を取得する仕事があるのですが、対象が学術用語であるのに加えて文脈情報を利用できない単語の羅列として入力するため、そこそこの割合で読みを正しく取得できないのが悩みの種です。

これまでは VBA の `GetPhonetic` を試したほか、形態素解析に目をつけて [形態素解析API](https://labs.goo.ne.jp/api/jp/morphological-analysis/) や [NMeCab](https://ja.osdn.net/projects/nmecab/) 、 Windows10 搭載の [JapanesePhoneticAnalyzer](https://docs.microsoft.com/en-us/uwp/api/windows.globalization.japanesephoneticanalyzer) を使ってきましたが、いずれも辞書のカスタマイズが不可能か（個人の技術力的に）高いハードルがありました。

最終的に Python 製の [janome](https://mocobeta.github.io/janome/) が比較的簡単に辞書を指定できるように作られているとわかったので、今回は powershell から `.py` ファイル経由で janome を呼び出して形態素解析をしてみようと思います。

参考： [powershell で python の出力を受け取る](https://qiita.com/AWtnb/items/d80ba79cf198e4cb5b74) 

# 事前準備
Python は scoop で入手しました。

```
PS > scoop install python
```

Python と同時に `pip.exe` がインストールされるので、多くの記事にある通り下記のコマンドで janome を入手します。

```
PS > pip install janome
```

# Python コードの作成
powershell から呼び出すファイルとして、以下のスクリプトを保存します。
`sys.argv[1]` でコマンドラインから渡される引数を取得しています。

```janome_tokenizer.py
import sys
import re
from janome.tokenizer import Tokenizer

target = sys.argv[1]
t = Tokenizer() # ここで辞書のディレクトリへのパスを指定（後述）
yomi = []
for token in t.tokenize(target, stream=True):
     word_surface = token.surface # 表層形
     word_part_of_speech = token.part_of_speech.split(",")[0] # 品詞名
     word_reading = token.reading # 読み
     if (word_part_of_speech == "記号") or (re.search("^\W+$", word_surface)):
          continue
     if word_reading != "*":
          yomi.append(word_reading)
     else:
          if re.search("^([ァ-ヴ]|[ぁ-ん]|[a-zA-Z]|\d|[・ー])+$", word_surface):
               yomi.append(word_surface)
          else:
               yomi.append("〓")
print("".join(yomi))
```
形態素解析の結果をループし、品詞が記号のものと表層形が非単語文字のみで構成されているものをスキップしながら読み情報をたどっていきます。読み情報が `*` であっても、表層形をそのまま読み情報として扱えるケースがあるので、正規表現での判定を挟んでいます。読み情報がまったく取得できない場合はゲタ `〓` を入れています。

# powershell コマンドレットの作成

```invoke-pythonjanome.ps1
function Invoke-PythonJanome ($s) {
    $pythonPath = "{0}\python_script\janome_tokenizer.py" -f $PSScriptRoot
    Invoke-Expression -Command ("python -B '{0}' '{1}'" -f $pythonPath, $s)
}
```
（詳しくは理解していないのですが、知らぬ間に `__pychache__` というフォルダが生成されるのを防ぐには実行オプションに `-B` を指定すればいいそうです）

この `invoke-pythonjanome.ps1` と同じディレクトリに `python_script` というフォルダを作成し、その中に上記の `janome_tokenizer.py` を配置します。

```
└─ invoke-pythonjanome.ps1
└─ python_script
    └─ janome_tokenizer.py     
```

あとは、ドットソースで読み込めばコマンドレットが使えるようになります。

```
# invoke-pythonjanome.ps1 があるディレクトリへ移動しておく
PS > . .\invoke-pythonjanome.ps1
```

# 動作確認
```
PS > Invoke-PythonJanome "渋谷ハチ公ではなく渋谷ヒカリエで待ち合わせです"
シブヤハチコウデハナクシブヤヒカリエデマチアワセデス

PS > Invoke-PythonJanome "松果体"
マツハテタイ
```

やはりデフォルトでは日常的な使用頻度が低い用語の形態素解析に失敗する模様……

# NEologd を使ってみる
これまで使いたいと思っていた形態素解析用の辞書の [NEologd](https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md) ですが、 @_likr 様がビルド済みの辞書ファイルを共有してくださっています（Qiita: [JanomeでNEologd辞書を使う](https://qiita.com/_likr/items/0fc845f59b4ad685cc06)）。ありがたくダウンロードさせていただき適当な場所に解凍します。
解凍後、 `neologd` ディレクトリへのパスを `janome_tokenizer.py` の `t = Tokenizer()` の引数として指定してやれば NEologd を使用した解析ができるようになります。

```
PS > Invoke-PythonJanome "松果体"
ショウカタイ
```

**弱点：異様なほどに遅い**
janome のデフォルト辞書を使用した場合に比べてやたらと時間がかかります（上記処理だけで30秒近く！）。高速化の方法についてどなたかご教授いただければ幸いです。
やはり自分で単語と読みを収集して csv 形式でも辞書を作るのが最速なのでしょうか…… :thinking: