WindowsやmacやLinuxにpipでPython用MeCabバインディングをいれる

# はじめに
ちゃお・・・†

個人的にですが、最近はWindowsのPythonでMeCabを使う機会が増えてきました。しかし、WindowsでMeCabのPythonラッパーを入れるには、ソースをダウンロードしたりsetup.pyを書き換えたりコンパイラをインストールしたりしないといけないので、とても面倒です。

そこで、WindowsでもmacでもUbuntuでもpipで簡単にMeCabのPythonラッパーを使えるものを公開しました！
https://pypi.org/project/mecab/

※ 過去にmecab-python-windowsというものを公開しましたが、そちらは今後アップデートしないつもりなので、**mecab-python-windowsを使っている人はこちらに乗り換えることを推奨**します。

# これは何？
インストール時のOSによってふるまいを変えることで、一つのパッケージで様々なOSに対応したMeCabラッパーです。たとえばWindowsの場合は、Microsoft Visual Studio の C++ コンパイラーで、mecab-pythonをビルドしてwheel形式にしたものが入ります。一方でmacやLinuxの場合は、バインディング用のC++コードをコンパイルするので、対象のコンピューターにC++コンパイラーが入っていないとインストールできません。

現在 Python2.7, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 に対応しています。どのバージョンも 32-bit と 64-bit 両方に対応しています。Windows 10 と macOS 10.14 と Ubuntu 18.04 と macOS 15で動作確認済みです。

ただしWindowsの64-bit版Pythonでは、下記の野良ビルドの64-bit版MeCabをインストールしていることを前提とします。
https://github.com/ikegami-yukino/mecab/releases

また、CabochaのWindows版は32-bitバイナリしか配布されていないため、**WindowsでCabochaと組み合わせて使いたい場合は32-bit版Pythonを使ってください。** (ややこしくてすみません)

それと、macOSにインストールする場合は、あらかじめApp StoreからXCodeをインストールする必要があります。

# mecabのメリット
- PyPIにてwheel形式で配布しているのでC++コンパイラの入っていないWindowsでも使える
- Windows, macOS, Linuxなどで共通して使える
- 公式Pythonバインディングと全く同じインターフェースなので、既存コードの書き換え不要
- 基本は公式Pythonバインディングと一緒なので処理が速い
- 公式Pythonバインディングのバグが修正されている
- `setup.py`の書き換え不要でインストール可能 (公式PythonバインディングではPython 3に対応するには`setup.py`の書き換えが必要)
- MeCab用辞書全てに対応
- SWIGやMeCab用辞書など余計なものが同梱されない

# インストール
```console
$ pip install mecab
```
あるいは

```console
$ python -m pip install mecab
```

で入れることが出来ます。

もしも古いPython 2.7でpipが入ってない場合は [get-pip.py](https://bootstrap.pypa.io/get-pip.py) をダウンロードしてPythonで実行するとpipが入ります。

もし`MeCab_wrap.cxx:178:11: fatal error: 'Python.h' file not found`みたいなエラーが出たら、

```
$ CPLUS_INCLUDE_PATH=`python-config --prefix`/Headers:$CPLUS_INCLUDE_PATH pip install mecab
```
を試してみてください。

# 使い方
## 基本

```py

>>> import MeCab
>>> t = MeCab.Tagger()
>>> sentence = "太郎はこの本を女性に渡した。"
>>> print(t.parse(sentence))
太郎    名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
この    連体詞,*,*,*,*,*,この,コノ,コノ
本      名詞,一般,*,*,*,*,本,ホン,ホン
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
女性    名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
渡し    動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。      記号,句点,*,*,*,*,。,。,。
EOS
>>> n = t.parseToNode(sentence)
>>> while n:
>>>     print(n.surface, "\t", n.feature)
>>>     n = n.next
           BOS/EOS,*,*,*,*,*,*,*,*
太郎     名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は       助詞,係助詞,*,*,*,*,は,ハ,ワ
この     連体詞,*,*,*,*,*,この,コノ,コノ
本       名詞,一般,*,*,*,*,本,ホン,ホン
を       助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
女性     名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ
に       助詞,格助詞,一般,*,*,*,に,ニ,ニ
渡し     動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た       助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。       記号,句点,*,*,*,*,。,。,。
         BOS/EOS,*,*,*,*,*,*,*,*
```

## 応用
IPA辞書及びmecab-ipadic-neologd辞書を対象としたコードの例です。

### 辞書の指定

```py
# NEologdなどの辞書を使うときは "-d" で辞書のディレクトリを指定
t = MeCab.Tagger("-d /path/to/dic/mecab-ipadic-neologd")
```

### 分かち書き

```py
t = MeCab.Tagger("-O wakati")
print(t.parse(sentence).rstrip())
#=> 太郎 は この 本 を 女性 に 渡し た 。
```
### 半角スペース混じりの固有名詞に対応した分かち書き
固有名詞が豊富なので辞書はNEologdがおすすめです。

```py
t = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd -F%m\\t -E\\n")
print(t.parse("DIR EN GREYのライブ行きたい").rstrip().split("\t"))
#=>['DIR EN GREY', 'の', 'ライブ', '行き', 'たい']
```

### 読みの取得

```py

# 読みの取得は "-O yomi"
t = MeCab.Tagger("-O yomi")
print(t.parse(sentence).rstrip())
#=> タロウハコノホンヲジョセイニワタシタ。
```

### 単語ごとの読みを取得

```py
t = MeCab.Tagger("-F%f[7]\\t -E\\n -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd")
print(t.parse(sentence).rstrip().split("\t"))
#=>['タロウ', 'ハ', 'コノ', 'ホン', 'ヲ', 'ジョセイ', 'ニ', 'ワタシ', 'タ', '。']
```

### 内容語と機能語の抽出
```py
CONTENT_WORD_POS = ("名詞", "動詞", "形容詞", "副詞")
IGNORE = ("接尾", "非自立", "代名詞")


def is_content_word(feature):
    return feature.startswith(CONTENT_WORD_POS) and all(f not in IGNORE for f in feature.split(",")[:6])

t = MeCab.Tagger()
n = t.parseToNode(sentence)
content_words = []
function_words = []
while n:
    if is_content_word(n.feature):
        content_words.append((n.surface, n.feature))
    elif not n.feature.startswith("BOS/EOS,"):
        function_words.append((n.surface, n.feature))
    n = n.next

print(content_words)  # 内容語
#=> [('太郎', '名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー'), ('本', '名詞,一般,*,*,*,*,本,ホン,ホン'), ('女性', '名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ'), ('渡し', '動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ')]

print(function_words)  # 機能語
#=> [('は', '助詞,係助詞,*,*,*,*,は,ハ,ワ'), ('この', '連体詞,*,*,*,*,*,この,コノ,コノ'), ('を', '助詞,格助詞,一般,*,*,*,を,ヲ,ヲ'), ('に', '助詞,格助詞,一般,*,*,*,に,ニ,ニ'), ('た', '助動詞,*,*,*,特殊・タ,基本形,た,タ,タ'), ('。', '記号,句点,*,*,*,*,。,。,。')]
```

### 原形に戻す
```py
t = MeCab.Tagger()
n = t.parseToNode("すごくいい本を渡した")
lemma = []
while n:
    if not n.feature.startswith("BOS/EOS,"):
        lemma.append(n.feature.split(",")[6])
    n = n.next
print(lemma)
#=> ['すごい', 'いい', '本', 'を', '渡す', 'た']
```

制約付き解析は過去記事を見てください。 https://qiita.com/yukinoi/items/4e7afb5e72b3a46da0f2

# 厚かましいお願い
もしも気に入ったら[mecabのGitHubリポジトリ](https://github.com/ikegami-yukino/mecab/)にスターをつけていただけると嬉しいです。たったの1クリックだけで、わたしの開発のモチベーションがアップします。