ルモーリン
ホーム 更新 Perl Sample サービス 雑談 鉄ゲタ Linux リンク 連絡先

日本語係り受け解析APIを使う

投稿:2021-11-30

漢字の歌詞入りMIDIファイルをMusicXMLファイルに変換する処理を作った際に、発音用に歌詞の漢字をひらがなにしました。 これまではYahooの日本語形態素解析APIを利用していました。 形態素解析は日本語処理APIのV1(Ver.1)で、他の日本語処理APIは既にV2(Ver.2)へ移行期間中(V1とV2が並行稼働)です。 いずれV2に移行するのではないかと予想して、今のうちにV2に移行しようと考えました。 形態素解析V2はないので日本語係り受け解析V2を使います。
日本語形態素解析 - Yahoo!デベロッパーネットワーク
日本語係り受け解析(V2) - Yahoo!デベロッパーネットワーク

上記のドキュメントの通り、登録したアプリケーションIDを付けてAPIのURLへJSONを投げるとJSONが戻ってきます。 ウチのサイトはMojoliciousで稼働していますからMojo::UserAgentを使えます。 JSON以外のポイントはにはリクエストヘッダのUser-AgentにIDを含めることくらいです。 MOJO::UserAgentの仕様が面白く、リクエストヘッダをハッシュリファレンスで入れています(初めて見た)。 発音用にひらがなに変換していますから、受け取ったレスポンスからひらがなを取り出し助詞の「は」「へ」を「わ」「え」に置き換えています。

	# ファイルの冒頭で宣言
	use Mojo::UserAgent;
	use Unicode::Japanese qw/ unijp /;

	my $lyric; # これに日本語が入っています。
        my $yahoo_client_id = $self->app->config("yahoo_client_id"); # Yahooに登録したアプリケーションID
        my $ua = Mojo::UserAgent->new;
        my $tx = $ua->post("https://jlp.yahooapis.jp/DAService/V2/parse" => {"User-Agent" => "Yahoo AppID: $yahoo_client_id", "Content-Type" => "application/json", Accept => "*/*"} => json => {
                id => "1234-1",
                jsonrpc => "2.0",
                method => "jlp.daservice.parse",
                params => {
                        q => $lyric,
                },
        });

        my @conv;
        if ($tx->result->is_success) {
                my $json = $tx->res->json;
                for (@{$json->{result}->{chunks}}) {
                        for (@{$_->{tokens}}) {
                                my @tokens = @{$_};
                                my $reading = $tokens[1]; # 平仮名
                                if ("助詞" eq $tokens[3]) {
                                        $reading = "わ" if "は" eq $reading;
                                        $reading = "え" if "へ" eq $reading;
                                }
                                $reading = unijp($reading)->kata2hira->getu; # 片仮名から平仮名に変換
                                $reading = unijp($reading)->h2z->getu; # 半角から全角に変換

                                push @conv, {
                                        surface => $tokens[0], # 変換前
                                        reading => $reading,
                                };
                        }
                }
        } else {
                $self->app->log->error("日本語係り受け解析サービス(V2)のエラー:" . $tx->res->message);
        }