こんばんは、Node.js/TypeScriptの環境でtakuyaa/kuromoji.jsを使って簡単に形態素分析ができたのでメモします。
yarn add kuromoji @types/kuromoji
使い方はこんな感じ
import kuromoji from 'kuromoji';
const tokenizer: kuromoji.Tokenizer<kuromoji.IpadicFeatures> = await new Promise((resolve, reject) => {
kuromoji
.builder({
dicPath: './node_modules/kuromoji/dict',
})
.build((err, _tokenizer) => {
if (!!err) {
reject(err);
}
resolve(_tokenizer);
});
});
export const tokenize = (text: string) => {
return tokenize(text)
}
本来やりたかったことは、文章から名詞だけを抽出したかったのですが、例えばキムチチャーハン
という名詞を抽出したくても、とても細かい単位で分かち書きされるのでキムチ
とチャーハン
に分割されてしまいます。こうならないよう連続する名詞を結合して取得してみました
type ProperNoun = {
position: number;
word: string;
};
/**
* 名詞を抽出する
* NOTE: 連続する名詞を束ねてそれらのみにフィルタリングする
*/
export const extractProperNounList(text: string) {
const pnList: ProperNoun[] = [];
let consecutiveWord: ProperNoun | null = null;
tokenize(text).forEach((result, i) => {
if (result.pos !== '名詞') {
if (consecutiveWord === null) return;
pnList.push(consecutiveWord);
consecutiveWord = null;
return
}
if (consecutiveWord === null) {
consecutiveWord = { word: '', position: result.word_position - 1 };
}
consecutiveWord.word = consecutiveWord.word + result.surface_form;
});
return pnList;
}
例えば僕の名前は田中太郎です。皆さんよろしくお願いいたします!好きな食べ物はキムチチャーハンと寿司ですね!
という文章を投げると結果はこんな感じです、いい感じですね 🥰
[
{ word: '僕', position: 0 },
{ word: '名前', position: 2 },
{ word: '田中太郎', position: 5 },
{ word: '皆さん', position: 12 },
{ word: 'お願い', position: 19 },
{ word: '好き', position: 28 },
{ word: '食べ物', position: 31 },
{ word: 'キムチチャーハン', position: 35 },
{ word: '寿司', position: 44 }
]