Herokuでmecab-python3を使う

#2021/03/01追記
@polm23 様よりunidic-liteをインストールする方法についてコメント欄で教えていただきましたので、やり方を以下にまとめます。こちらのほうが明らかに簡単でした。教えていただきありがとうございました。

##ファイル構成

```
- mecabheroku
    - Procfile
    - runtime.txt
    - requirements.txt
    - main.py
```

```:Procfile
web: python main.py
```

```runtime.txt
python-3.8.5
```

```requirements.txt
mecab-python3
unidic-lite
```

```main.py
import MeCab
m=MeCab.Tagger()
print(m.parse('神ってる'))
```

##デプロイ

```
$ cd mecabheroku
$ heroku login
$ heroku create [app name]
$ git init
$ heroku git:remote -a [app name]
$ git add .
$ git commit -am "first"
$ git push heroku master
$ heroku logs
（略)
2021-03-01T13:05:59.251402+00:00 app[web.1]: 神	カミ	カミ	神	名詞-普通名詞-一般			1
2021-03-01T13:05:59.251418+00:00 app[web.1]: っ			っ	補助記号-一般
2021-03-01T13:05:59.251419+00:00 app[web.1]: てる	テル	テル	てる	助動詞	下一段-タ行	終止形-一般
2021-03-01T13:05:59.251419+00:00 app[web.1]: EOS
```

#概要
<b>2021/03/01追記：以下は、unidic-liteを用いる方法と比べると手間の多いやり方となっています。一応、記録として残しておきます。(追記ここまで）</b>

Herokuでmecab（mecab-python3）を使う方法についてすでにいろいろ記事があるのですが、自分の環境でどうもうまく行かない部分があったので、解決した方法をまとめておきます。

具体的には、下記ページなどのやり方を参照していたのですが、`MeCab.Tagger()`の宣言でエラーを起こすという問題で詰まっていました。

[HerokuにMeCabを入れる際ハマっていた記録](https://qiita.com/kzuzuo/items/1b3e9c9af57bd4464690)
[Herokuでpython+mecab+ffmpegを使う](https://qiita.com/Sashimimochi/items/2da79bda71dfc1b555cd)

`heroku logs --tail`でherokuのログを参照したところ、mecabrcが見つからないというエラーが出ていました。そこで、環境変数でmecabrcの場所を明示的に指定したところ、無事アプリを使うことができました。環境変数を設定する部分はaptとlinuxbrewという違いはあるのですが、下記サイトを参考にできました。

[Heroku環境でnatto/mecab gemを使えるようにする](https://qiita.com/amishiratori/items/a32f8addcb6d6f6c2e11)
#環境
macOS Catalina 10.15.4
python 3.8.0
#事前準備
Herokuのアカウントを作っておきます。
Heroku ClIをインストールしてターミナルからherokuを触れるようにしておきます。
#プロジェクトの作成
プロジェクトを作成し、念の為、python仮想環境を立ち上げ、mecab-python3をインストールします。
その後、requirements.txtを生成します。

```
$ mkdir mecabheroku
$ cd mecabheroku
$ python -m venv .
$ source bin/activate
$ pip install mecab-python3
$ pip freeze > requirements.txt
$ cat requirements.txt
mecab-python3==1.0.1
```

なお、単にherokuにデプロイするだけであれば、下記でもよいです。
(仮想環境の立ち上げやpip installは不要です)

```
$ mkdir mecabheroku
$ cd mecabheroku
$ nano requirements.txt
$ cat requirements.txt
mecab-python3
```

#設定ファイルの追加
Herokuの設定ファイルを追加します。なお、herokuが対応するpythonのバージョンが更新されるなどして、デプロイが上手く行かない場合があります。その時は、runtime.txtを修正してください。


```:runtime.txt
python-3.8.0
```

```:Procfile
web: python main.py
```

```:.buildpacks
https://github.com/sunny4381/heroku-buildpack-linuxbrew.git
```

```:.cellar
mecab
mecab-ipadic
```

main.pyを作成します。

```Python:main.py
import MeCab
m=MeCab.Tagger()
print(m.parse('神ってる'))
```
ここまででファイル構成は以下のとおりです。

```
- mecabheroku
    - .buildpacks
    - .celler
    - Procfile
    - bin
        - ...
    - include
        - ...
    - lib
        - ...
    - main.py
    - pyvenv.cfg
    - requirements.txt
    - runtime.txt
```
#Herokuへのデプロイ
Herokuにgitプロジェクトを作成し、リモートサーバの設定をします。

```
$ heroku login
$ git init
$ heroku create mecabheroku
$ heroku git:remote -a mecabheroku
```

Herokuにログインしてappを作成します。
またbuildパッケージの追加と環境変数の設定を行います。

```
$ heroku buildpacks:set https://github.com/heroku/heroku-buildpack-multi.git
$ heroku buildpacks:add --index 2 heroku/python
$ heroku config:add LD_LIBRARY_PATH=/app/.linuxbrew/lib
$ heroku config:set MECAB_PATH=/app/.linuxbrew/lib/libmecab.so
$ heroku config:set MECABRC=/app/.linuxbrew/etc/mecabrc
```

Herokuにプロジェクトをデプロイします。

```
$ git add .
$ git commit -am "first"
$ git push heroku master
```

Herokuのログを確認し、形態素解析が行えていればOKです。

```
$ heroku logs
(前略)
2020-09-21T11:37:34.857593+00:00 heroku[web.1]: Starting process with command `python main.py`
2020-09-21T11:37:37.883740+00:00 app[web.1]: 神	名詞,一般,*,*,*,*,神,カミ,カミ
2020-09-21T11:37:37.883758+00:00 app[web.1]: っ��	助詞,格助詞,連語,*,*,*,って,ッテ,ッテ
2020-09-21T11:37:37.883759+00:00 app[web.1]: る	助動詞,*,*,*,文語・ル,基本形,る,ル,ル
2020-09-21T11:37:37.883759+00:00 app[web.1]: EOS
(後略)
```

#補足
##MECABRCを設定しない場合
環境変数MECABRCをアンセットすると以下のエラーが確認できます。

```
$ heroku config:unset MECABRC
$ heroku logs --tail
(前略)
2020-09-21T11:41:13.609126+00:00 heroku[web.1]: Starting process with command `python main.py`
2020-09-21T11:41:15.534271+00:00 heroku[web.1]: Process exited with status 1
2020-09-21T11:41:15.569956+00:00 heroku[web.1]: State changed from starting to crashed
2020-09-21T11:41:15.572394+00:00 heroku[web.1]: State changed from crashed to starting
2020-09-21T11:41:15.493565+00:00 app[web.1]: 
2020-09-21T11:41:15.493591+00:00 app[web.1]: Failed initializing MeCab. Please see the README for possible solutions:
2020-09-21T11:41:15.493591+00:00 app[web.1]: 
2020-09-21T11:41:15.493592+00:00 app[web.1]: https://github.com/SamuraiT/mecab-python3#common-issues
2020-09-21T11:41:15.493592+00:00 app[web.1]: 
2020-09-21T11:41:15.493593+00:00 app[web.1]: If you are still having trouble, please file an issue here, and include the
2020-09-21T11:41:15.493593+00:00 app[web.1]: ERROR DETAILS below:
2020-09-21T11:41:15.493593+00:00 app[web.1]: 
2020-09-21T11:41:15.493594+00:00 app[web.1]: https://github.com/SamuraiT/mecab-python3/issues
2020-09-21T11:41:15.493594+00:00 app[web.1]: 
2020-09-21T11:41:15.493594+00:00 app[web.1]: issueを英語で書く必要はありません。
2020-09-21T11:41:15.493594+00:00 app[web.1]: 
2020-09-21T11:41:15.493600+00:00 app[web.1]: ------------------- ERROR DETAILS ------------------------
2020-09-21T11:41:15.493600+00:00 app[web.1]: arguments:
2020-09-21T11:41:15.494419+00:00 app[web.1]: error message: [ifs] no such file or directory: /usr/local/etc/mecabrc
2020-09-21T11:41:15.494424+00:00 app[web.1]: ----------------------------------------------------------
2020-09-21T11:41:15.494469+00:00 app[web.1]: Traceback (most recent call last):
2020-09-21T11:41:15.494471+00:00 app[web.1]: File "main.py", line 2, in <module>
2020-09-21T11:41:15.494675+00:00 app[web.1]: m=MeCab.Tagger()
2020-09-21T11:41:15.494713+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.8/site-packages/MeCab/__init__.py", line 124, in __init__
2020-09-21T11:41:15.494947+00:00 app[web.1]: super(Tagger, self).__init__(args)
2020-09-21T11:41:15.494976+00:00 app[web.1]: RuntimeError
(後略)
```

プログラムが/usr/local/etc/mecabrcを読みにいったが存在しなかったと言われています。
したがってデプロイ前に環境変数でmecabrcの場所を明示的に指定する必要があり、その場所は、デプロイ中(git push heroku master実行後)の下記のログから`/app/.linuxbrew/etc/mecabrc`とわかります。

```
(前略)
remote:        To enable mecab-ipadic dictionary, add to /app/.linuxbrew/etc/mecabrc:
(後略)
```

よって下記コマンドが必要となるのですが、他の参考サイトではMECABRについては特に触れられていなかったので、詰まりました。
ひょっとしたらherokuの仕様変更などがあって、最近（2020年9月ごろ？）になって、MECABRCの設定が必要になった、とかなのかもしれません。

```
$ heroku config:set MECABRC=/app/.linuxbrew/etc/mecabrc

```
##自作のmecabrc
linuxbrewが作ったものではなく、自作のmecabrcを使うことができないか、試してみたのですが、うまくできませんでした。
具体的にはプロジェクトの親フォルダ直下にmecabrcを配置して、MECABRCに/app/mecabrcをセットしたのですが、mecabrcが存在しないというエラーが出てしまいました。
ローカルのディレクトリ構成とheroku内のディレクトリ構成は必ずしも対応しない部分がある、ということなのかも知れません。

```
$ heroku config:set MECABRC=/app/mecabrc
```
##mecab-ipadic-neologd
完全な余談ですが、本当はheroku上でmecab-ipadic-neologdを使いたかったのですが、容量の問題でできないこともわかりました。herokuの無料枠で使える容量は500MBですが、mecab-ipadic-neologdは900MB近くあるため、デプロイに失敗します。
また前節でmecabrcを参照できなかったのと同じ問題で、mecab-ipadic-neologdまでのパスをどう設定すればよいかよくわかっていない、という問題もあります。

##slug size is too large
mecabは容量が大きいのでプロジェクトのほかファイルの容量によっては、`sulg size is too large`的なエラーが出てデプロイに失敗することがあります。
その場合は下記の手順により、pipのインストールをデプロイ後に行うようにすると、うまくいくことがあるようです。

```:Procfile
web: bash run.sh
```

```:run.sh
pip install -r requirements.txt
python main.py
```

参考：
[Django + KoNLPy + MeCabアプリをHerokuにデプロイ](https://mnmandahalf.hatenablog.com/)
[Herokuでpython+mecab+ffmpegを使う](https://t-n-clark.hatenadiary.jp/entry/2019/10/07/113000)