プログラミング

PythonとLINE Messaging APIでLINE BOTを作ってみた

Pythonと「LINE Messaging API」を使って、送信したメッセージと同じメッセージを返すLINE BOTを作ってみました。

Pythonのフレームワークである「Flask」とPaasの「Heroku」も使います。

なお、Flaskの使い方やHerokuでのデプロイ方法などの説明は省略し、Herokuでアプリケーションをデプロイしてあるものとして話を進めていきます。

LINE Developersのアカウントを作成

LINE BOTを作るにあたり、まずLINEの開発者登録用ページより、開発者アカウントを作成する必要があります。

開発者登録用ページ
https://developers.line.biz/ja/

「LINEアカウントでログイン」をクリックして、メールアドレスとパスワードを入力してログインします。

次に開発者用アカウントの情報を入力。名前とメールアドレスを入力して、規約にチェックし、「Create my account」をクリック。

これで開発者アカウントの作成は完了です。右下で言語を変えられるので日本語にしておきます。

プロバイダーを作成

「新規プロバイダー作成」のボタンから新しいプロバイダーを作成します。

プロバイダー名を入力して「作成」をクリック。

チャネルを作成

次にチャネルを作成する必要があります。

チャネルを作成するのに、チャネルの種類を選択するのですが、今回は「Messaging API」を選択。

設定に必要な下記項目を入力していきます。

  • チャネルアイコン
  • チャネル名(必須)
  • チャネル説明(必須)
  • 大業種(必須)
  • 小業種(必須)
  • メールアドレス(必須)
  • プライバシーポリシーURL
  • サービス利用規約URL

今回は次のようにしました。

  • チャネル名→テスト用アプリ
  • チャネル説明→LINE Messaging APIのテスト用アプリ
  • 大業種→ウェブサービス
  • 小業種→ウェブサービス(ユーティリティ)

LINE BOTを作成

まずアクセストークンを取得する必要があります。

アクセストークンとは、外部からLINEを使うための許可証のようなものです。

アクセストークンは「Messaging API設定」タブをクリックして、一番下にある「チャネルアクセストークン」より発行することができます。

発行されたアクセストークンはあとでプログラムに記述します。

ユーザーからのメッセージを受け取って返信する機能を使うにはWebhookをオンにする必要があります。

「応答メッセージ」の「編集」をクリックすると応答設定ページが開くので、そこでWebhookをオンにします。

ついでに、詳細設定の応答メッセージはオフにしておきます。(画像はオンになっていますが、オフに。)

オンにしていると、こんな感じでメッセージを送るたびに自動応答メッセージが返ってきます。

また、ユーザーからのメッセージを任意のURL(サーバー)に転送して内容を処理させるために、「Webhook URL」の設定をします。

今回はHerokuのサーバーを使用してユーザーのメッセージを処理させます。

Webhook URLは「アプリのURL/callback」を入力します。

「検証」をクリックするとエラーが表示されますが、実際にアプリを起動させて問題なければ気にしなくて大丈夫です。

「Webhookの利用」もオンにしておきます。

基本的な設定はここまで。

次に必要なライブラリをインストールしたり、プログラムを書いていきます。

アクセストークンとチャンネルの秘密鍵をセット

まず、アクセストークンを「line_bot_api」に、チャンネルの秘密鍵を「handler」にセットするのですが、変数を使ってセットした方がわかりやすいかなと思うので、次のような書き方にしています。

ACCESS_TOKEN = “YOURE_CHANNEL_ACCESS_TOKEN”
SECRET = “YOUR_CHANNEL_SECRET”

line_bot_api = LineBotApi(ACCESS_TOKEN)
handler = WebhookHandler(SECRET)

「YOURE_CHANNEL_ACCESS_TOKEN」がアクセストークンで、「YOUR_CHANNEL_SECRET」はチャンネルの秘密鍵を記述する箇所です。

なお、チャンネルの秘密鍵は「チャネル基本情報」のタブから取得できます。「チャネルシークレット」と書かれているところです。

「Messaging API SDK」を導入

今回は公式に提供されている「LINE BOT SDK」とFlaskを使ってバックエンドサーバーを使用するので、ライブラリ「Messaging API SDK」を導入します。

Herokuでデプロイ済みのプロジェクトに移動して、以下のコマンドで「Messaging API SDK」を導入。

pip3 install line-bot-sdk

インストールしたら、「requirements.txt」に「LINE BOT SDK」を反映させる必要があります。

pip3 freeze > requirements.txt

そしてLINE BOTに必要なコードを記述しますが、完成形は次のようになります。

app.py
from flask import Flask, request, abort

from linebot import (
 LineBotApi, WebhookHandler
)
from linebot.exceptions import (
 InvalidSignatureError
)
from linebot.models import (
 MessageEvent, TextMessage, TextSendMessage
)

app = Flask(__name__)

ACCESS_TOKEN = “YOURE_CHANNEL_ACCESS_TOKEN”
SECRET = “YOUR_CHANNEL_SECRET”

line_bot_api = LineBotApi(ACCESS_TOKEN)
handler = WebhookHandler(SECRET)

@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’

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
 line_bot_api.reply_message(
  event.reply_token,
  TextSendMessage(text=event.message.text))

if __name__ == “__main__”:
 app.run()

ポイントとなるのは@handler.add以下の部分。仕組みは、ユーザーがLINE BOTにメッセージを送信すると、LINEのサーバーを経由して開発者が立ち上げたサーバーに情報が送信されるようになっています。ちなみにこの流れを「イベント」といいます。

このイベントに対してどのように返信を行うかをプログラムで決めるのです。

app.py
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
 line_bot_api.reply_message(
  event.reply_token,
  TextSendMessage(text=event.message.text))

今回の場合は、単にユーザーが送信したメッセージをおうむ返しで返信するようになっています。

「event.message.text」でユーザーが送信したメッセージを取得。LineBotApiのインスタンスから「.reply_message()」を呼ぶことで、返信しています。

第一引数は固定で「event.reply_token」を、第二引数には返信するメッセージを指定します。

ここではテキストデータを送信したいので「TextSendMessage()」を使っています。

実際にLINE BOTを使ってみる

必要なコードが書けたら、Herokuでデプロイします。

そして、チャネルの管理画面い表示されているQRコードで読み取ると、作ったアプリにアクセスすることができます。

友達に追加して使ってみます。

おうむ返しのLINEボットができました。

画像のリプライ機能を実装してみる

ついでに、画像をリプライする設定に変更してみます。

「.reply_message()」の第二引数を「TextSendMessage()」から「ImageSendMessage()」に変更し、リプライに使用する画像のURLを指定します。

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
 line_bot_api.reply_message(
  event.reply_token,
  ImageSendMessage(
  original_content_url=’https://1.bp.blogspot.com/-eaDZ7sDP9uY/Xhwqlve5SUI/AAAAAAABXBo/EcI2C2vim7w2WV6EYy3ap0QLirX7RPohgCNcBGAsYHQ/s400/pose_syanikamaeru_man.png’,
  preview_image_url=’https://1.bp.blogspot.com/-eaDZ7sDP9uY/Xhwqlve5SUI/AAAAAAABXBo/EcI2C2vim7w2WV6EYy3ap0QLirX7RPohgCNcBGAsYHQ/s400/pose_syanikamaeru_man.png’))

画像はフリーのイラスト配布サイト「いらすとや」で適当に選んで使用しています。

また、以下も追記します。

from linebot.models import (
 ImageMessage, ImageSendMessage
)

デプロイし直して確認すると、何を送信しても、指定した画像が返ってきます。

今度はユーザーが画像を送信したら、同じ画像を返すようにしてみます。

そのためにはユーザーから送信されたコンテンツを取得する必要があるのですが、「.get_message_content()」でユーザーが送信した画像を取得できます。

これに画像のIDを指定することで画像データを読み出します。

以下のコードでは、ユーザーから送信された画像をサーバーに保存してリプライする仕組みを実装しています。

@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
 message_content = line_bot_api.get_message_content(event.message.id)
 
 with open(“static/” + event.message.id + “.jpg”, “wb”) as f:
  f.write(message_content.content)
  line_bot_api.reply_message(
   event.reply_token,
   ImageSendMessage(
    original_content_url=FQDN + “/static/” + event.message.id + “.jpg”,
    preview_image_url=FQDN + “/static/” + event.message.id + “jpg”
   )
  )

@handler.add()のmessageは「ImageMessage」の指定に変わっています。

また、変数FQDNにはHerokuで割り当てられたURLを指定します。

完成形は次の通り。

app.py
from flask import Flask, request, abort

from linebot import (
 LineBotApi, WebhookHandler
)
from linebot.exceptions import (
 InvalidSignatureError
)
from linebot.models import (
 MessageEvent, TextMessage, TextSendMessage, ImageMessage, ImageSendMessage
)

app = Flask(__name__)

ACCESS_TOKEN = “YOURE_CHANNEL_ACCESS_TOKEN”
SECRET = “YOUR_CHANNEL_SECRET”

FQDN = “Herokuで割り当てられたURL”

line_bot_api = LineBotApi(ACCESS_TOKEN)
handler = WebhookHandler(SECRET)

@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’

@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
 message_content = line_bot_api.get_message_content(event.message.id)
 
 with open(“static/” + event.message.id + “.jpg”, “wb”) as f:
  f.write(message_content.content)
  line_bot_api.reply_message(
   event.reply_token,
   ImageSendMessage(
    original_content_url=FQDN + “/static/” + event.message.id + “.jpg”,
    preview_image_url=FQDN + “/static/” + event.message.id + “jpg”
   )
  )

if __name__ == “__main__”:
 app.run()

なお、画像の保存先であるstaticフォルダを生成しておかないといけないのですが、あらかじめ何かしらファイルを入れておかないと、Herokuにデプロイしてもフォルダの作成が認識されないみたいです。

挙動を確認してみると、送信した画像と同じ画像が返ってきました。

参考書籍

ここでは、LINE Developersのアカウントを作成、Python+Flask+Heroku+LINE Messaging APIでおうむ返しをするLINE BOTを作成する方法を紹介しました。

なお、今回の内容は以下の本に基づいて書いています。


Python + LINEで作る人工知能開発入門 – Flask + LINE Messaging APIでの人工知能LINEボットの作り方

Kindle Unlimited会員なら追加料金なしで読むことができます。

ちなみに本ではGoogleの人工知能関連APIを組み合わせてLINE BOTを作るところまで書かれています。

Leave a Comment