36
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

この記事は,NTTドコモアドベントカレンダー第11日目の記事になります。

こんな人に読んでほしい

  • 口コミやツイートの分析をしている人
  • 顔文字・絵文字・URLを抽出するツールを探している人
  • 自然言語処理に興味がある人

※ 最後の付録で実装したソースコードを公開してます!

1. はじめに

自然言語処理にとって前処理は非常に重要です。
特に、商品の口コミやツイートは顔文字やURLなどのノイズが多く、前処理しないままでは思い通りの分析ができません😇
そこで本記事では、SNSテキストから顔文字・絵文字・URLを抽出して削除/置換するための前処理方法について紹介したいと思います。

前処理例
prepro_example.png

2. 必要なもの

ツール

インストール方法
$ pip install nagisa emoji

データ

抽出対象のSNSテキストデータです。ご自身で収集した口コミやツイートをご用意下さい。
もし手元に無い場合は、MTNTデータなどを使って試しましょう。

  • MTNT: Machine Translation of Noisy Text
    • MTNTデータセットは、Redditという投稿型のソーシャルサイトの書き込みを収集したものです(日本の2ちゃんねるのような掲示板サイトに近いです)。
    • スラングや文法誤り、顔文字・絵文字などのノイズを多く含むSNSテキストの機械翻訳の研究用に無償公開されています。

3. 実践: SNSテキストを前処理してみよう

それでは、実際にSNSテキストから顔文字・絵文字・URLを抽出してみましょう。

3.1 方針

顔文字・URLの抽出はnagisa、絵文字の抽出はemojiを使います。

3.2 顔文字の抽出方法

nagisaは日本語テキスト用の形態素解析ツールですが、
うまく使いこなせば顔文字やURLを抽出することができます。

こちらの記事でも言及されている通り、nagisaでは顔文字やURLを1つの単語として単語分割することができます。

しかし、\(^o^)/ などのを含む顔文字は1つの単語として分割することは難しいようです。
\/補助記号 (^o^)/補助記号 //補助記号 のように、3つの単語に分かれてしまいます。

nagisaの解析結果

nagisa_sample.png

ですが、うまく処理すれば、このような顔文字も抽出することができます。
仕組みは単純で、顔文字の手を事前に定義して、顔文字の周辺からを一緒に抽出します。

import nagisa
import unicodedata
def extract_kaomoji(text):
    """ 与えられたテキストから抽出した顔文字リストを返却する。
        → \(^o^)/, m(_ _)m などの 手を含む顔文字があれば、それも抽出する
    """
    results = nagisa.extract(text, extract_postags=['補助記号'])
    words = results.words
    kaomoji_words = []
    kaomoji_idx = [i for i, w in enumerate(words) if len(w) >= KAOMOJI_LEN]
    kaomoji_hands = ['', '', '', 'm', 'O', 'o', '', '/', '\\', ''] 
    # 顔文字と手を検索
    for i in kaomoji_idx:
        kaomoji = words[i] # 顔文字列
        try:
            # 顔文字の左手
            if words[i-1] in kaomoji_hands and 0 < i:
                kaomoji = words[i-1] + kaomoji
            # 顔文字の右手
            if words[i+1] in kaomoji_hands:
                 kaomoji = kaomoji + words[i+1]
        except IndexError:
            pass
        finally:
            kaomoji_words.append(kaomoji)
    return kaomoji_words

text = "今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg"
text = unicodedata.normalize('NFKC', text) # NFKC正規化
print(extract_kaomoji(text))
# => ['\\(^o^)/']

text = "ごめんなさいm(-_-)m"
text = unicodedata.normalize('NFKC', text) # NFKC正規化
print(extract_kaomoji(text))
# => ['m(-_-)m']

これで、テキストから顔文字を抽出することができました。

抽出結果

今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg
顔文字: \(^o^)/

ごめんなさいm(-_-)m
顔文字: m(-_-)m

3.3 URLの抽出

URLの抽出はシンプルです。
必要な品詞の単語だけを抽出する関数nagisa.extractで必要な品詞タグにURLを条件付けるだけで、URLを抽出することができます。

import nagisa
import unicodedata

def extract_url(words):
    results = nagisa.extract(text, extract_postags=['URL'])
    return results.words

text = "今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg"
text = unicodedata.normalize('NFKC', text) # NFKC正規化
print(extract_url(text))
# => ['https://hogehogehogehoge.jpg']

抽出結果

今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg
URL: https://hogehogehogehoge.jpg

3.4 絵文字の抽出

絵文字の抽出も簡単です。
絵文字はUnicodeで定義されているため、文字のUnicodeを確認してその文字が絵文字かどうかを判定します。
emojiで絵文字のUnicodeリストを使うことができます。

import emoji
import nagisa
import unicodedata

def extract_emoji(words):
    return [w for w in words if w in emoji.UNICODE_EMOJI]


text = "今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg"
text = unicodedata.normalize('NFKC', text) # NFKC正規化
print(extract_emoji(text))
# => ['🏙', '❗']

text = "日本語のテキストから絵文字😉を抽出するよ❗"
text = unicodedata.normalize('NFKC', text) # NFKC正規化
print(extract_emoji(text))
# => ['😉', '❗']

抽出結果

今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg
絵文字: 🏙, ❗

日本語のテキストから絵文字😉を抽出するよ❗
絵文字: 😉, ❗

4. おわりに

テキストから顔文字・絵文字・URLを抽出する前処理方法を紹介しました。

本記事で紹介した前処理(一部)は、今年ドコモとNTTが参加したWMT19のRobustness taskに投稿したシステムでも使っています。
論文でも前処理について書いていますので、ツイートや口コミの分析に取り組んでいる方のお役に立てれば幸いです。

最後に、本記事を書く際に参考にさせていただいた記事を紹介します。
テキスト前処理についてとても良くまとめられているので、ぜひ参考にしてみて下さい。

テキスト前処理に関する記事のまとめ


付録

本記事で実装したコード(全文)です。

ソースコード

import emoji
import nagisa
import unicodedata

KAOMOJI_PH = "<Kaomoji>"
URL_PH = "<URL>" 
EMOJI_PH = "<Emoji>"
KAOMOJI_LEN = 5

def extract_kaomoji(text):
    """ 与えられたテキストから抽出した顔文字リストを返却する。
        → \(^o^)/, m(_ _)m などの 手を含む顔文字があれば、それも抽出する
    """
    results = nagisa.extract(text, extract_postags=['補助記号'])
    words = results.words
    kaomoji_words = []
    kaomoji_idx = [i for i, w in enumerate(words) if len(w) >= KAOMOJI_LEN]
    kaomoji_hands = ['', '', '', 'm', 'O', 'o', '', '/', '\\', ''] 
    # 顔文字と手を検索
    for i in kaomoji_idx:
        kaomoji = words[i] # 顔文字列
        try:
            # 顔文字の左手
            if words[i-1] in kaomoji_hands and 0 < i:
                kaomoji = words[i-1] + kaomoji
            # 顔文字の右手
            if words[i+1] in kaomoji_hands:
                 kaomoji = kaomoji + words[i+1]
        except IndexError:
            pass
        finally:
            kaomoji_words.append(kaomoji)
    return kaomoji_words

def extract_url(words):
    results = nagisa.extract(text, extract_postags=['URL'])
    return results.words

def extract_emoji(text):
    results = nagisa.tagging(text) # 形態素解析
    words = results.words
    return [w for w in words if w in emoji.UNICODE_EMOJI]

def replace(text, target_list, PH):
    for trg in target_list:
        text = text.replace(trg, PH)
    return text

def delete(text, target_list):
    for trg in target_list:
        text = text.replace(trg, "")
    return text

text = "今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg"
text = unicodedata.normalize('NFKC', text) # NFKC正規化

# 入力
print("対象テキスト: {}\n".format(text))

# 抽出
kaomoji_list = extract_kaomoji(text)
url_list = extract_url(text)
emoji_list = extract_emoji(text)

# 抽出結果
print("顔文字: {}".format(kaomoji_list))
print("URL: {}".format(url_list))
print("絵文字: {}\n".format(emoji_list))


# 削除
deleted_text = delete(text, kaomoji_list + url_list + emoji_list)
print("削除: {} \n".format(deleted_text))

# 置換
replaced_text = replace(text, kaomoji_list, KAOMOJI_PH)
replaced_text = replace(replaced_text, url_list, URL_PH)
replaced_text = replace(replaced_text, emoji_list, EMOJI_PH)
print("置換: {} \n".format(replaced_text))

出力例

対象テキスト: 今日は渋谷スクランブルスクエアに行ってきた\(^o^)/ 夜景🏙サイコー❗️ https://hogehogehogehoge.jpg

顔文字: ['\\(^o^)/']
URL: ['https://hogehogehogehoge.jpg']
絵文字: ['🏙', '❗']

削除: 今日は渋谷スクランブルスクエアに行ってきた 夜景サイコー️  

置換: 今日は渋谷スクランブルスクエアに行ってきた<Kaomoji> 夜景<Emoji>サイコー<Emoji>️ <URL> 
36
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?