Help us understand the problem. What is going on with this article?

悟空語ジェネレーターをぺぇそん(Python)でも作ってみたぞ!えーぴーえぇ(API)化もしたぞ!

(2019/2/23更新 PyPIに登録し、pip installで使えるようになりました)

まとめ

Pythonモジュール版について

使い方

ぺぇぴーえぇ(PyPI)に登録済みなので、pip installで使えます。

(venv) $ pip install gokulang

なお、

  • 形態素解析モジュールであるjanome
  • 日本語をローマ字に変換するモジュールであるpykakasi
  • その他semidbm, six

に依存していますので一緒にインストールされます。

(venv) $ pip list
Package    Version
---------- -------
gokulang   1.0.1  
Janome     0.3.7  
pip        10.0.1 
pykakasi   0.94   
semidbm    0.5.1  
setuptools 39.1.0 
six        1.12.0 

無事インストールされたら、gokulang.pyからGokuLangクラスをimportし、インスタンス化の上、translateメソッドに日本語文章を渡してください。

(venv) $ python
>>> from gokulang.gokulang import GokuLang
>>> g = GokuLang()
>>> g.translate('FF外から失礼します')
'FFげぇからしつれぇすっぞ'

以下環境で動作確認しています。

  • Python 3.6.6
  • Janome 0.3.7
  • pykakasi 0.94
  • semidbm 0.5.1
  • six 1.12.0

Web API版について

使い方

パラメータtextに日本語文章を入れてください。

レスポンスの

  • originalには入力値であるtextそのまま
  • translatedには変換後の文章

が入ります。

GETの場合

$ curl https://gokulang.herokuapp.com/api/?text=お願いします
{"original": "お願いします", "translated": "おねげぇすっぞ"}

POSTの場合

$ curl https://gokulang.herokuapp.com/api/ -X POST -d 'text=もう帰ります'
{"original": "もう帰ります", "translated": "もうけぇっぞ"}

なお、API側にデータベースなどは持っていませんので、POSTを実行しても何かが更新されるようなことはありません。

変換処理の大まかな流れ

考え方は悟空語ジェネレーターとほぼ同じです。

  1. janomeで形態素解析を行い、各単語とその読み、品詞を取得
  2. 各単語をpykakasiでローマ字に変換
  3. ローマ字を悟空独特の言い回しに変換 e.g.) a + i => e + e
  4. 変化のあったローマ字をRomanKanaTable ジェネレーターを参考に平仮名に戻す。変化の無かった語は、当初の内容に戻す。

ただ、悟空語ジェネレーターのソースを解析して作ったわけではないので、変換結果は大なり小なり差はあるかと思います。

また、悟空語ジェネレーターに存在した以下仕様には現時点では対応はしていません。

  • 一人称をおら、二人称をおめぇに変換
  • 悟空語なまりの強さを選択可能

今回の個人開発で学んだこと

1. テストコードの重要性

2019年2月現在、私はコードを全く書くことの無い仕事をしており、恥ずかしながら今回の個人開発で初めてテストコードを書きました。

悟空語変換ロジックを作り上げる過程では、ロジックの追加・修正の都度、従来上手く行っていた変換がおかしくなることがありました。

>>> g.translate('登録したぞ')
'登録すっぞぞ'

頻発するデグレートの発見と再修正を効率良く行う上で、テストコードは不可欠でした。

test_gokulang.py
import unittest
from gokulang import GokuLang


class GokuLangTest(unittest.TestCase):
    def setUp(self):
        self.G = GokuLang()

    def tearDown(self):
        pass

    def test_ai_ae(self):
        q = '最初の試合は緊張するだろうけど、今のお前なら大丈夫だ'
        a = 'せぇしょのしえぇは緊張するだろうけど、今のおめぇならでぇじょうぶだ'
        self.assertEqual(a, self.G.translate(q))

    def test_ei_ae_oi(self):
        q = '冷静に考えろ、奴は強いぞ'
        a = 'れぇせぇにかんげぇろ、奴はつえぇぞ'
        self.assertEqual(a, self.G.translate(q))

    def test_oe(self):
        q = 'ここを越えるよ'
        a = 'ここをけぇるよ'
        self.assertEqual(a, self.G.translate(q))

    def test_kaeru(self):
        q = 'もう帰ります'
        a = 'もうけぇっぞ'
        self.assertEqual(a, self.G.translate(q))

    def test_non_reading_shimasu(self):
        q = 'FF外から失礼します'
        a = 'FFげぇからしつれぇすっぞ'
        self.assertEqual(a, self.G.translate(q))

    def test_ta(self):
        # 見送っぞ にならないことのテスト
        q = '見送った'
        a = '見送った'
        self.assertEqual(a, self.G.translate(q))

    def test_ta2(self):
        # 登録すっぞぞ にならないことのテスト
        q = '登録したぞ'
        a = '登録したぞ'
        self.assertEqual(a, self.G.translate(q))

    def test_nai(self):
        # みえっぞ にならないことのテスト
        q = '見えない'
        a = '見えねぇ'
        self.assertEqual(a, self.G.translate(q))

    def test_da(self):
        # あそっぞ や あそぶぞ にならないことのテスト
        q = '遊んだ'
        a = '遊んだ'
        self.assertEqual(a, self.G.translate(q))

    def test_dekami(self):
        q = 'ぱいぱいでか美'
        a = 'ぺぇぺぇでか美'
        self.assertEqual(a, self.G.translate(q))


if __name__ == '__main__':
    unittest.main()

2. Web API化

Web APIを作るのも初めてで、Djangoにて手探りで作ってみました。
APIとしての考え方やお作法など、何か間違っている点があればご指摘いただけると幸いです。

api/views.py
import json

from django.views.generic import View, TemplateView
from django.http.response import HttpResponse

from .gokulang.gokulang import GokuLang


class GokuLangView(View):

    def get(self, request):

        text = request.GET.get('text') if request.GET.get('text') else ''

        g = GokuLang()
        translated = g.translate(text)

        response = {'original': text, 'translated': translated}

        return HttpResponse(json.dumps(response, ensure_ascii=False), content_type='application/json')

    def post(self, request):

        text = request.POST.get('text') if request.POST.get('text') else ''

        g = GokuLang()
        translated = g.translate(text)

        response = {'original': text, 'translated': translated}

        return HttpResponse(json.dumps(response, ensure_ascii=False), content_type='application/json')

# ...

def getdef postもやっていることがほぼ同じなので、コードが冗長ですね・・・。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした