#概要
AIチャットBOT +スクレイピング = POST + API +BS4の学習の体験に役立てる記事となることを願います。
最終的な目的として、Lineの1つのBotによりいろいろなサービスと連携でき統合していきたいと思います。
(秘書みたいなものを作りたい。)
##成果物
https://liff.line.me/1645278921-kWRPP32q?accountId=621otkwb&openerPlatform=native&openerKey=talkroom%3Amessage#mst_challenge=XC5NTvj9TrdRKQK5uqwVADAMrvCYbugYb9F4RvYD2jI
##環境
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の準備
https://note.com/pro_buncho/n/n37ff0614dd36
LINE公式アカウントを作成し、対応します。
###3.スクレイピングのコード作成
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のテスト
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をコーディング
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)
##参考
https://qiita.com/hiro0236/items/84581c5e4481185d4a5c
他のスタンプや、写真が来た時などの処理振り分けを行えば、写真判別や写真をサーバーへ格納などもできそうです。