Qiitaコーパスを作る会 2️⃣前処理をする

# はじめに
[前回の記事](https://qiita.com/LeftLetter/items/24ed8f792f56a2ec2392)でQiitaの全記事を取得したので、次は以下の記事を参考に前処理を行っていきます。

[自然言語処理における前処理の種類とその威力](https://qiita.com/Hironsan/items/2466fe0f344115aff177)

今回のシリーズで作ったソースコードは[GitHub](https://github.com/LeftLetter/qiita_corpus)に置いてあります。


# 前処理をする

## 記事の抜き出し

Qiita APIで取得できる記事データには、`rendered_body`にHTML形式、`body`にマークダウン形式の記事情報が含まれています。

今回は、パースのしやすいHTML形式の方を使用します。

```python:json_to_text.py
# --------------------------------------------------
# Qiita APIから取得したデータの記事部分を抜き出しファイル出力
# --------------------------------------------------
import json
from datetime import datetime, timedelta
from bs4 import BeautifulSoup
import os

start = datetime.strptime(os.getenv('START_DATE'), '%Y-%m-%d')  # 開始日を設定
end = datetime.strptime(os.getenv('END_DATE'), '%Y-%m-%d')  # 終了日を設定

for i in range((end - start).days):
    today = (start + timedelta(i)).strftime('%Y-%m-%d')
    print(today)

    # データ読み込み
    with open('data/qiita_' + today + '.json') as json_data:
        articles = json.load(json_data)

        # 記事の集約
        for article in articles:
            soup = BeautifulSoup(article['rendered_body'], 'html.parser')
            # 本文の抜き出し
            sentences = soup.find_all('p')
            for sentence in sentences:
                text = sentence.text + '\n'
                # ファイル書き込み
                with open('data/qiita.txt', 'a') as f:
                    f.write(text)

```

このプログラムを実行すると、`data`フォルダの中に、HTMLから`p`タグ（段落）部分のみを抽出した`qiita.txt`が生成されます。

## 形態素解析
次に形態素解析を行います。日本語は英語のように単語同士が分かれていないので、単語ごとに分割する必要があるためです。

形態素解析器にはMeCabを使用しています。
注）MeCabは別途インストールが必要です。[NEologd](https://github.com/neologd/mecab-ipadic-neologd)辞書と一緒に入れてしまうのが楽でオススメです。

```python:text_to_wakati.py
# --------------------------------------------------
# テキストファイルを分かち書き
# --------------------------------------------------
import os
import MeCab


# データ読み込み
with open('data/qiita.txt') as text_data:
    tagger = MeCab.Tagger(
        '-Owakati -b ' + os.getenv('MECAB_BUFFER') + ' -d ' + os.getenv('MECAB_DIC_PATH'))
    line = text_data.readline()
    while line:
        # 分かち書き
        result = tagger.parse(line)
        line = text_data.readline()
        if result != None:
            # ファイル書き込み
            with open('data/qiita_wakati.txt', 'a') as f:
                f.write(result)

```

テキストをまとめて全てMeCabに投げると、`too long sentence.`エラーが出てしまったため１行ずつ渡しています。

また、バッファは以下の設定をしています。ここは取得した記事によって変わってくるかと思います。

```
MECAB_BUFFER=203714
```

## 単語の正規化
最後に単語の正規化を行います。
今回は、以下の処理のみ行いました。

* 英字大文字を全て小文字に
* 日本語の半角を全角に
* 一部の記号を統一
* 数字を全て0に

数字を全て0にしてしまうのは、今回に限ってはやめた方が良いかもしれません。なぜなら、技術用語における数字は結構重要なケースも多いと考えられるからです（バージョンなど）。

```python:preprocessing.py
# --------------------------------------------------
# 分かち書きされたテキストの前処理
# --------------------------------------------------
import os
import re
import jaconv


# データ読み込み
with open('data/qiita_wakati.txt') as wakati_data:
    data = wakati_data.read()
    # 大文字→小文字
    data = data.lower()
    # 半角→全角
    data = jaconv.h2z(data)
    # 記号（-など）の正規化
    data = jaconv.normalize(data)
    # 数字の置き換え
    data = re.sub(r'[0-9]+', '0', data)

    # ファイル書き込み
    with open('data/qiita_corpus.txt', 'w') as f:
        f.write(data)

```

# おわりに
前回→
[Qiitaコーパスを作る会 1️⃣Qiitaの全記事を取得してみる](https://qiita.com/LeftLetter/items/24ed8f792f56a2ec2392)
次回→
[Qiitaコーパスを作る会 3️⃣単語埋め込みの様子を見てみる](https://qiita.com/LeftLetter/items/fcbe827c8af66160a429)