🗾

ja_sentence_segmenter で文区切りするときに、句読点のピリオドと小数点のピリオドを区別する

2021/11/26に公開

日本語の文区切りをいい感じに行う ja_sentence_segmenter というライブラリがあり、便利です。

https://qiita.com/wwwcojp/items/3535985007aa4269009c

さて、手元にあるテキストには句読点として「。」ではなく「.」が用いられていました。これに対応すべく、以下のように区切りルールを追加しました。

 import functools
 
 from ja_sentence_segmenter.common.pipeline import make_pipeline
 from ja_sentence_segmenter.concatenate.simple_concatenator import  concatenate_matching
 from ja_sentence_segmenter.normalize.neologd_normalizer import  normalize
 from ja_sentence_segmenter.split.simple_splitter import  split_newline, split_punctuation
 
-split_punc2 = functools.partial(split_punctuation, punctuations=r"。 !?")
+split_punc2 = functools.partial(split_punctuation, punctuations=r".。 !?")
 concat_tail_no = functools.partial(concatenate_matching, former_matching_rule=r"^(?P<result>.+)(の)$", remove_former_matched=False)
 segmenter = make_pipeline(normalize, split_newline, concat_tail_no, split_punc2)

しかしながら、これでは問題がありました。

こんにちは.私の体重は52.3kgです.

という文章が

['こんにちは.', '私の体重は52.', '3kgです.']

と区切られてしまうのです。句読点のピリオドと小数点のピリオドが区別できない問題 です。

困ってしまいましたが、しばらくリポジトリを眺めていると、解決策がきちんと実装されていることに気づきました。concatenate_matching を使えば特定のパターンにマッチするテキストを連結してくれます。具体的には、引数のformer_matching_rule で連結する2つのうち前の方の文字列パターン、latter_matching_rule で後の方の文字列パターンを指定できます。
今回で言えば、小数点の場合はピリオドの前後で数字があるはずなので、以下のようにすればよいです。

 import functools
 
 from ja_sentence_segmenter.common.pipeline import make_pipeline
 from ja_sentence_segmenter.concatenate.simple_concatenator import  concatenate_matching
 from ja_sentence_segmenter.normalize.neologd_normalizer import  normalize
 from ja_sentence_segmenter.split.simple_splitter import  split_newline, split_punctuation
 
 split_punc2 = functools.partial(split_punctuation, punctuations=r".。 !?")
 concat_tail_no = functools.partial(concatenate_matching, former_matching_rule=r"^(?P<result>.+)(の)$", remove_former_matched=False)
+concat_decimal = functools.partial(concatenate_matching, former_matching_rule=r"^(?P<result>.+)(\d.)$", latter_matching_rule=r"^(\d)(?P<result>.+)$", remove_former_matched=False, remove_latter_matched=False)
-segmenter = make_pipeline(normalize, split_newline, concat_tail_no, split_punc2)
+segmenter = make_pipeline(normalize, split_newline, concat_tail_no, split_punc2, concat_decimal)

これで

こんにちは.私の体重は52.3kgです.

という文章が

['こんにちは.', '私の体重は52.3kgです.']

と区切られるようになりました。

Discussion