Twitter APIで取得したデータをクリーニングする(前処理)

前回、TwitterのAPIを使って、学習用データを簡易に取得する方法について記事化しました。

Twitter APIを使ってツイートデータを取得する(Essential版)

自然言語処理の勉強をしていて一番大変なのは、学習用のデータを集めることです。いくつかのオープンデータが提供されていますが、公的研究機関や、大学関係者などに利用…

取得したデータは、かなり自由に書かれています。このままでは学習データとして使えませんので、いくつかのフィルターをかけて整形していきます。

(1) HTMLや@で始まるIDの削除
リンク先を示すHTMLや宛先を示すアカウントIDなどは削除しておきます。

(2)全角半角の統一
カタカナや英数文字、記号などの全半角を統一します。

(3)空白文字(スペース)の処理
全半角のスペースを統一したり、文章の前後にある空白を削除します。

参考にしたサイトはこちらです。neologd/mecab-ipadic-neologd

Sample Code

pythonでの文字列変換には、正規表現を使って操作するreを使います。以下のコードでは、@から始まるワード、#から始まるワード、https://から始まるワードを''(文字列なし)に置き換えて除去しています。

import re

def clean_text(text):
    replaced_text = re.sub(r'[@@]\w+', '', text) 
    replaced_text = re.sub(r'#\w+', '', replaced_text)  
    replaced_text = re.sub(r'https\S+', '', replaced_text) 
    return replaced_text

# \wはアルファベット、数字、アンダスコア( _ )のどれかの1文字と一致
# \Sは半角スペース、タブ、改行以外の1文字と一致
# []は含まれるどれか一文字と一致
# +は、直前の文字の1回以上の繰り返しと一致

実行結果は以下のようになります。

cleaned_text = clean_text('RT @abc12_3def: 今年はWBC⚾のあと、ラクビー🏈とバスケ🏀のワールドカップも控えるスポーツイヤー。 #スポーツ 詳細はこちら https://abcd.ef/ghi.html')
print(cleaned_text)

#result
RT : 今年はWBC⚾のあと、ラクビー🏈とバスケ🏀のワールドカップも控えるスポーツイヤー。 詳細はこちら 

これだけではうまくいかないケースもあるかと思いますので、ご利用される場合には結果を確認しながらご利用ください。

全半角の統一、空白の処理については、先述の参考サイトのコードを転載させていただきます。こちらも基本的にはreを使った文字列の置き換えになっていますので、必要に応じて修正して使えば良いかと思います。例えば「〜(チルダ)」を除去するようになっていましたが、私はコメントアウトしました。

# encoding: utf8
from __future__ import unicode_literals
import re
import unicodedata

def unicode_normalize(cls, s):
    pt = re.compile('([{}]+)'.format(cls))

    def norm(c):
        return unicodedata.normalize('NFKC', c) if pt.match(c) else c

    s = ''.join(norm(x) for x in re.split(pt, s))
    s = re.sub('-', '-', s)
    return s

def remove_extra_spaces(s):
    s = re.sub('[  ]+', ' ', s)
    blocks = ''.join(('\u4E00-\u9FFF',  # CJK UNIFIED IDEOGRAPHS
                      '\u3040-\u309F',  # HIRAGANA
                      '\u30A0-\u30FF',  # KATAKANA
                      '\u3000-\u303F',  # CJK SYMBOLS AND PUNCTUATION
                      '\uFF00-\uFFEF'   # HALFWIDTH AND FULLWIDTH FORMS
                      ))
    basic_latin = '\u0000-\u007F'

    def remove_space_between(cls1, cls2, s):
        p = re.compile('([{}]) ([{}])'.format(cls1, cls2))
        while p.search(s):
            s = p.sub(r'\1\2', s)
        return s

    s = remove_space_between(blocks, blocks, s)
    s = remove_space_between(blocks, basic_latin, s)
    s = remove_space_between(basic_latin, blocks, s)
    return s

def normalize_neologd(s):
    s = s.strip()
    s = unicode_normalize('0-9A-Za-z。-゚', s)

    def maketrans(f, t):
        return {ord(x): ord(y) for x, y in zip(f, t)}

    s = re.sub('[˗֊‐‑‒–⁃⁻₋−]+', '-', s)  # normalize hyphens
    s = re.sub('[﹣-ー—―─━ー]+', 'ー', s)  # normalize choonpus
    #s = re.sub('[~∼∾〜〰~]', '', s)  # remove tildes       
    s = s.translate(
        maketrans('!"#$%&\'()*+,-./:;<=>?@[¥]^_`{|}~。、・「」',
              '!”#$%&’()*+,-./:;<=>?@[¥]^_`{|}〜。、・「」'))

    s = remove_extra_spaces(s)
    s = unicode_normalize('!”#$%&’()*+,-./:;<>?@[¥]^_`{|}〜', s)  # keep =,・,「,」
    s = re.sub('[’]', '\'', s)
    s = re.sub('[”]', '"', s)
    return s