LINE MessagingAPIとPythonのスクレイピングで記事検索botをつくってみた

LINE MessagingAPIとPythonのスクレイピングライブラリのBeautifulSoup4を使って、対象アカウントに対して送った単語を含む記事を予め指定したURLから検索するbotをつくりました。
Pythonのスクレイピングの勉強も兼ねて、せっかくなる使い道のあるものを作りたいと思い試しにつくってみました。
<br><br>

## 前提
* MacBook 2017モデルにて開発
* OSは10.12(Sierra)
* Pythonは3.6.5
* botの実行環境はHeroku
<br><br>

## メッセージ授受処理
ほとんどLINE社が提供しているサンプルのままです。handle_messageメソッド内で送られてきた単語を受け取り、その単語を引数にscrape.pyのgetNewsメソッドを呼び出します。

```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 urllib.request
import os
import json
import scrape as sc


app = Flask(__name__)


#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)


@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


# メッセージリプライ
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):

    # ユーザからの検索ワードを取得
    word = event.message.text

    # 記事取得関数を呼び出し
    result = sc.getNews(word)

    # 応答メッセージ（記事検索結果）を送信
    line_bot_api.reply_message(
    event.reply_token,
    TextSendMessage(text=result)
    )


if __name__ == "__main__":
#    app.run()
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)
```
<br><br>

## スクレイピング処理
指定したURLから記事をスクレイピングし、取得した結果のうち引数wordのを記事件名に含むニュースのみ戻り値に格納します。
スクレイピング部分はURLによって大きく変わりますが、件名とURLはどこのサイトでも変わらないので多少は流用できるでしょう。

```python:scrape.py
import urllib.request
from bs4 import BeautifulSoup
import json
import requests


# アクセス先URLとUAを設定
url = 'https://sports.yahoo.co.jp/news/list?id=jleague'
ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) '\
     'AppleWebKit/537.36 (KHTML, like Gecko) '\
     'Chrome/67.0.3396.99 Safari/537.36 '

# 記事取得関数
def getNews(word):

    # 下記はアクセス先に合わせて修正しスクレイピング
    req = urllib.request.Request(url, headers={'User-Agent': ua})
    html = urllib.request.urlopen(req)
    soup = BeautifulSoup(html, "html.parser")
    main = soup.find('div', attrs={'class': 'modBody'})
    topics = main.find_all(attrs={'class': 'linkMain'})

    # 該当記事カウント変数と結果格納リスト
    count = 0
    list = []

    # スクレイピング結果から引数wordを含む記事を結果リストに格納
    for topic in topics:
        if topic.contents[0].find(word) > -1:
            list.append(topic.contents[0])
            list.append(topic.get('href'))
            count += 1
    if count == 0:
        result.append("該当記事はありません")

    # リスト内の要素間に改行を挿入して返却
    result = '\n'.join(list)
    return result
```
<br><br>

## LINE MessagingAPIは色々遊べそう
今回はスクレイピングでしたが、他のAPIと連携してみたりと色々できそうです。LINEはいろんなサービスのプラットフォームとして活用できそうですね。
<br><br>

## 参考
スクレイピング以外の部分はほぼ以下の記事を参考にさせていただきました。
[PythonでLine botを作ってみた](https://qiita.com/krocks96/items/67f7510b36945eb9689b)