【Python】平成最後だから流行語で振り返る LINE  BOTを作った話


# 結論（何を作ったか）
LINE BOTに"流行語"と入力してメッセージを送ると、歴代の流行語がランダムで返される

## 背景
まもなく平成が終わる。35歳の自分はそのほんとんどを平成とともに過ごしてきた。青春を謳歌し、世の中に起こる様々なことを平成で体験した。

何かを思い出すとき、振り返るとき、きっかけは人それぞれだと思う。それは音楽だったり、匂いだったり、映像だったりする。

今回、平成を振り返る一つの手段として、誰でもわかりやすいのが***流行語***ではないかと思った。
そこで、Pythonの学習をかねて、平成を振り返るきっかけにできるLINE BOTを作ることにした。

## 全体の流れ

① Wikipediaから過去の流行語をスクレイピング　(pandasを利用)
   　※厳密には昭和の流行語も含まれている　総数：398語
② LINE BOTに***流行語***と入力してメッセージを送る
③ LINE BOTからランダムで***過去の流行語***が返ってくる
④ 返ってきた***流行語***を眺めて懐かしむ

こんな感じ↓
<img width="375" alt="line_ss.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400635/15bbda3d-e693-beb6-35b6-7aa269ab7668.jpeg">




## 実際のコード

まずはWikipediaから流行語をスクレイピング。めちゃくちゃ苦労した。最終的には力技。
もっとシンプルで効率的なコードがあると思う。

初めはRequestsとBeautiful Soupを使ってチャレンジしたが、抽出対象がaタグに含まれていたため不要なものまで抽出されてしまった。

```python:scrap.py
# モジュールの読み込み
import pandas as pd

# wikipediaの流行語ページを指定
url = "https://ja.wikipedia.org/wiki/%E6%96%B0%E8%AA%9E%E3%83%BB%E6%B5%81%E8%A1%8C%E8%AA%9E%E5%A4%A7%E8%B3%9E"

# 受賞語が含まれるテーブルから必要な情報を取得
dfs1 = pd.read_html(url, match="受賞語", header=0)
dfs1 = pd.concat([dfs1[0], dfs1[1], dfs1[2]], sort=True)
dfs1 = dfs1[["年度", "受賞語"]]
dfs1.to_csv("list.csv", header=None, index=False)

# 年間大賞が含まれるテーブルから必要な情報を取得
dfs2 = pd.read_html(url, match="年間大賞", header=0)
dfs2 = (dfs2[0])
dfs2 = dfs2[["年度", "年間大賞"]]
dfs2.to_csv("list2.csv", header=None, index=False)

# 金賞が含まれるテーブルから必要な情報を取得
dfs3 = pd.read_html(url, match="金賞", header=0)
dfs3 = (dfs3[0])
dfs3 = dfs3[["年度", "金賞"]]
dfs3.to_csv("list3.csv", header=None, index=False)
```

抽出した3ファイルの結合がpandasで、どうやってもうまく行かず、最終的にcatコマンドで結合。
※CSVの結合がうまくいかなかったコードは後述

続いて、LINE BOTの処理。

```python:main.py
# モジュールの読み込み
from flask import Flask,request,abort
from linebot import LineBotApi,WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent,TextMessage,TextSendMessage
import csv
import random

app=Flask(__name__)
# トークン等の情報を格納
YOUR_CHANNEL_ACCESS_TOKEN="**********************"
YOUR_CHANNEL_SECRET="****************************"
line_bot_api=LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler=WebhookHandler(YOUR_CHANNEL_SECRET)

# Herokuへの指示
@app.route("/callback",methods=["POST"])
def callback():
    signature=request.headers["X-Line-Signature"]

    body=request.get_data(as_text=True)
    app.logger.info("Request body"+body)

    try:
        handler.handle(body,signature)
    except InvalidSignatureError:
        abort(400)
    return "OK"

# LINEからのメッセージ受け取り処理
@handler.add(MessageEvent,message=TextMessage)
def handle_message(event):
    # 入力された文字列を格納
    push_text = event.message.text

    # 返信する文字列の条件
    if push_text == "流行語":
        f = open("all_list.csv", "r") # 流行語が入ったファイル
        csv_data = csv.reader(f)
        data = [e for e in csv_data]
        h = random.choice(data) # ランダムで抽出
        reply_text = h[0] + "の流行語は・・・\n" + h[1] # 年度と流行語をメッセージに格納
        f.close()
    else:
    # 流行語以外の文字が入力された場合の返答
        reply_text = "流行語と入力してください！"

    # 返答する内容を格納
    line_bot_api.reply_message(event.reply_token,TextSendMessage(text=reply_text))

if __name__=="__main__":
    port=int(os.getenv("PORT",5000))
    app.run(host="0.0.0.0",port=port)
```
流行語は都度スクレイピングするのではなくファイル（流行語が入っている）から呼び出すようにした。
LINE BOTの処理は条件のところを工夫すれば、もっと面白いことができそう。
今回の一番のキモはWikipediaから流行語をスクレイピングしてくるところだった。苦労したが、ザクッとデータを抽出できたときは気持ちよかった。

## まとめ

単純なBOTかもしれないがスクレイピング、 LINE BOT、Herokuなど、作る過程で様々な技術に触れることができた。

LINE BOTを作る過程でオウム返しができるBOTが公式に紹介されていた。これを写経しながら作ることも学習だと思うが、これだけだと学習してても面白くないし、学習意欲がわかないと思う。***学習するときはただマネをするだけではなく、ちょっとしたアイデアやオリジナリティを付加すると、楽しいし、学習も進む。***

流行語で平成を振り返り、こんなこともあったなー、あのときこんなことしてたなー、なんて懐かしい気持ちになった。令和になる前に完成できてよかった。

## CSVファイルの結合（うまくいかなかったコード）

```python:concat.py
# モジュールの読み込み
import glob
import csv
import pandas as pd

# 3ファイルのCSVを格納
all_file = glob.glob("*.csv")

# 3ファイルを結合
list = []
for file in all_file:
    list.append(pd.read_csv(file))
df = pd.concat(list, sort=False)

# 統合した3ファイルを1ファイルとして出力
df.to_csv("all_list.csv")
```
これを実行すると結合はされるが、余分なカラム（'Unnamed: 0'）まで追加されてしまう。さらに先頭行のカラムの位置もずれる。`del df['Unnamed: 0']`で削除もできるが、なぜ挿入されてしまうのかわからなかった。

## 参考にした情報

- [新語・流行語大賞](https://ja.wikipedia.org/wiki/%E6%96%B0%E8%AA%9E%E3%83%BB%E6%B5%81%E8%A1%8C%E8%AA%9E%E5%A4%A7%E8%B3%9E)
- [Python, pandasでwebページの表（htmlのtable）をスクレイピング](https://note.nkmk.me/python-pandas-web-html-table-scraping/)
- [LINE+Python+天気API を活用してチャットボットを作成してみた](https://qiita.com/neonsk/items/807e7398e71e18da1b01)
- [【Python】CSVファイルを読み込んでリストに格納](https://algorithm.joho.info/programming/python/csv-reader-data-to-list/)
- [Pythonでリストからランダムに要素を選択するchoice, sample, choices](https://note.nkmk.me/python-random-choice-sample-choices/)