LoginSignup
7
5

More than 3 years have passed since last update.

Python_FlaskでLine Chat BOT(スクレイピング+API)

Posted at

概要

AIチャットBOT +スクレイピング = POST + API +BS4の学習の体験に役立てる記事となることを願います。
最終的な目的として、Lineの1つのBotによりいろいろなサービスと連携でき統合していきたいと思います。
(秘書みたいなものを作りたい。)

成果物

環境

Python:Flask
Heroku
line-bot-sdk
BeautifulSoup4
pya3rt(リクルートのAIチャット)
requests

構成

構成
project
├── main.py
├── requirements.txt
├── Procfile
└── runtime.txt

手順

1.準備リクルートAIchatBotのAPIの取得

Talk APIのAPI KEYが必要です。
https://a3rt.recruit-tech.co.jp/product/talkAPI/

2.LINEの準備

LINE公式アカウントを作成し、対応します。

3.スクレイピングのコード作成

Python
import requests
import json
from bs4 import BeautifulSoup

url = 'https://tenki.jp/forecast/9/46/8610/43100/'
res = requests.get(url)

soup = BeautifulSoup(res.text, "html.parser")
print(soup)



found = soup.find_all('p',class_='weather-telop')
found2 = soup.find_all('h3',class_='left-style')

textA = found2[0].text + found[0].text +'\n'+found2[1].text + found[1].text
textA = '熊本の天気\n'+textA
print(textA)

テスト動作を別途作成しテストします。

4.AIchatのテスト

Python
import pya3rt
apikey = "#########" #自分のAPIキーを設定する
client = pya3rt.TalkClient(apikey)

if __name__ == '__main__':
  words = input("INPUT MESSAGE >")
  #CTRL+Cで終了
  while words!="":
    response = client.talk(words)
    print("Bot >"+((response['results'])[0])['reply'])
    words = input("INPUT MESSAGE >")
    words =response['results']

main.pyへスクレイピンとAIチャットのAPIを取り込んだLineBOTをコーディング

Python
from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)
import os
import requests
import pprint
from bs4 import BeautifulSoup

#AI chatbotモジュール
import pya3rt

app = Flask(__name__)

#環境変数取得
# LINE Developersで設定されているアクセストークンとChannel Secretをを取得し、設定します。
#セキュリティ上heroku側で環境変数を設定すると良いです。
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)

#Webhookからのリクエストをチェックします。
@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)

    # handle webhook body# 署名を検証し、問題なければhandleに定義されている関数を呼び出す。
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:# 署名検証で失敗した場合、例外を出す。
        abort(400)
        # handleの処理を終えればOK
    return 'OK'

#LINEでMessageEvent(普通のメッセージを送信された場合)が起こった場合に、def以下の関数を実行します。
#reply_messageの第一引数のevent.reply_tokenは、イベントの応答に用いるトークンです。 
#第二引数には、linebot.modelsに定義されている返信用のTextSendMessageオブジェクトを渡しています。

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):

    push_text = event.message.text

   #熊本天気という特定文字に対して下記処理を行います。ワイルドカードを使えば抽出する形になるでしょう。
    if push_text == "熊本天気":       
        url = 'https://tenki.jp/forecast/9/46/8610/43100/'
        res = requests.get(url)

        soup = BeautifulSoup(res.text, "html.parser")
        #print(soup)

        found = soup.find_all('p',class_='weather-telop')
        found2 = soup.find_all('h3',class_='left-style')


        textA = found2[0].text + found[0].text
        #textA = '熊本の天気を気象庁からスクレイピングしてきました。\n'+textA

        reply_text =  textA

        line_bot_api.reply_message(event.reply_token,[TextSendMessage('熊本の天気を気象庁からスクレイピングしてきました。'),TextSendMessage(textA),TextSendMessage(found2[1].text + found[1].text)])

    elif push_text == "自己紹介":
        reply_text = "初めまして。\n私にはAIchatがAPI連携で搭載されています。\n色んな会話をして下さい。"   


    elif push_text == "犬はかわいい":        
        reply_text = "はい、 その通りです。\n動画を撮り、家族で共有すべきだと思います。\nコロナのせいで、皆にあいにくいいま動画コンテンツは利用するべきです。"   
        A = []
        A.append(reply_text)
        reply_text = "お犬様は正義!"   
        A.append(reply_text)
        line_bot_api.reply_message(event.reply_token,[TextSendMessage(A[0]),TextSendMessage(A[1])])

    elif push_text == "転職したい":
        reply_text = "Let's Action"   

    else:
       ai_message = talk_ai(push_text)
        reply_text = ai_message
     #特定もじいがいはAiからのメッセージにて対応させます。   

    line_bot_api.reply_message(event.reply_token,TextSendMessage(text=reply_text))


#上部でtalk_ai使用時に下記関数が使われます。
def talk_ai(word):
    apikey = "###########"
    client = pya3rt.TalkClient(apikey)
    reply_message = client.talk(word)
    return reply_message['results'][0]['reply']

# ポート番号の設定
if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)

参考

他のスタンプや、写真が来た時などの処理振り分けを行えば、写真判別や写真をサーバーへ格納などもできそうです。

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5