結論(何を作ったか)
LINE BOTに"流行語"と入力してメッセージを送ると、歴代の流行語がランダムで返される
背景
まもなく平成が終わる。35歳の自分はそのほんとんどを平成とともに過ごしてきた。青春を謳歌し、世の中に起こる様々なことを平成で体験した。
何かを思い出すとき、振り返るとき、きっかけは人それぞれだと思う。それは音楽だったり、匂いだったり、映像だったりする。
今回、平成を振り返る一つの手段として、誰でもわかりやすいのが流行語ではないかと思った。
そこで、Pythonの学習をかねて、平成を振り返るきっかけにできるLINE BOTを作ることにした。
全体の流れ
① Wikipediaから過去の流行語をスクレイピング (pandasを利用)
※厳密には昭和の流行語も含まれている 総数:398語
② LINE BOTに流行語と入力してメッセージを送る
③ LINE BOTからランダムで過去の流行語が返ってくる
④ 返ってきた流行語を眺めて懐かしむ
実際のコード
まずはWikipediaから流行語をスクレイピング。めちゃくちゃ苦労した。最終的には力技。
もっとシンプルで効率的なコードがあると思う。
初めはRequestsとBeautiful Soupを使ってチャレンジしたが、抽出対象がaタグに含まれていたため不要なものまで抽出されてしまった。
# モジュールの読み込み
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の処理。
# モジュールの読み込み
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ファイルの結合(うまくいかなかったコード)
# モジュールの読み込み
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']
で削除もできるが、なぜ挿入されてしまうのかわからなかった。