iT邦幫忙

0

(番外篇-LineBot)[不做怎麼知道系列之Android開發者的30天後端養成故事 Day25] - 來問問你認識的Youtuber的訂閱數吧 #Django #LineBotSDK #ngrok

Sam 2020-03-06 10:46:321893 瀏覽

https://ithelp.ithome.com.tw/upload/images/20200306/20124548v5xuBiTX2o.png

哈囉,我們又見面了,昨天我們介紹了爬蟲,爬到指定的 Youtuber 訂閱數,今天來把這功能串到 Line 的聊天機器人吧!

https://ithelp.ithome.com.tw/upload/images/20200306/20124548rks22Cd2ea.png

(這一篇還沒有要上架到 GAE,那是下一篇的事情,這篇先把 django 開在本地端就好)

Day23 的最後,我們創建了一個叫做 linebot 的 django 專案,裡面有 webhookcrawler 兩個 app,顧名思義,其中的 webhook app,就是要跟 line 做結合的 app,而 crawler app 就是用來取得資料並回傳給 webhook app 的。

這時候的專案架構應該長這樣

  • linebot (project dir)

    ├ linebot (project settings)

    ├ webhook (app)

    ├ crawler (app)

    └ manage.py

這篇會直接串接昨天的爬蟲,對於第一次搭建 Line Chatbot 的捧油們會有點吃力,你可以參考 手把手教你搭建聊天機器人(LineBot+Python+QnAMaker+Heroku)-02建造LineBot Backend Server 並部署至Heroku 的 EchoBot 部分,這篇也是用 Django 做的,跟我們不同的地方是,它把 server 放到 Heroku,我們是放到 GAE,但在今天的篇幅中,不會提到部屬到雲端。

1. 申請 Line Developer、創建一個 Messaging API Channel

Line Developer 詳細的申請、創建過程,可以參考 LineBot+Python,輕鬆建立聊天機器人,這一篇它是用 Flask 框架所做的,Flask 是個輕量級的 Python Web Framework,很適合拿來搭建聊天機器人這類輕量的應用,但我們已經用了 Django 一段時間,所以就試試看用 Django 來架聊天機器人囉~

反正最後應該要長這樣 XD

你要能進到你的 Channel 設定頁面,確認三點

  • 在你的 Channel 裡面可以找到 channel secretwebhook settingschannel access token 三個欄位
  • Use webhook 這個欄位是有開啟的
  • Auto-reply messages 這個欄位是關閉的

確認完以上三點後,就可以進行到下個環節。

到目前為止,你已經可以在 Messaging API 分頁,透過 Bot basic IDQR code,在 line 加 chatbot 好友,可是現在 chatbot 什麼功能都沒有,我們就來想辦法讓它有功能。

https://ithelp.ithome.com.tw/upload/images/20200306/20124548esVBecM1KZ.png

2. 把 linebot 串到自己的 django server

這句話的意思是

將使用者對 linebot 所說的話,導向你的 django server,這樣就可以在 django 端,寫下你要處理的邏輯。

2.1 怎麼個串法 ?

在 Line Chatbot,就是透過 Webhook url 串到你的 django server 所在地,你可以把 webhook 想像成一個雙頭鉤,勾住 server 和 line 兩端,這樣就搭建起兩端溝通的橋樑了 !

https://ithelp.ithome.com.tw/upload/images/20200306/20124548YU0kzCurDy.png

2.2 Server 架在自己的電腦,怎麼生成 Webhook url ?

我一開始聽到 Webhook 的時候,就聽的霧沙沙,不能理解這是什麼鬼東東,但其實就是你 server 所在的網址,也或許是你的 server 的 IP,那麼你可能會想問,如果我的 server 架在我的電腦上,沒有固定 IP 也沒有網址,這樣該怎麼辦 ?,這時候就會想起在 Day16 所提到的 ngrok 啦 ! 它可以把你電腦的某個 port 開出來,而且最重要的是,有支援 SSL,也就是 https,因為 line 的 webhook 只支援 https。

透過 ngrok 生成 webhook url

詳細的使用方法,參考 Day16

$ ngrok http 8000 (代表開放出 8000 的 port)

ngrok by @inconshreveable                                                (Ctrl+C to quit)

Session Status                online
Account                       rongson (Plan: Free)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://xxx.ngrok.io -> http://localhost:8000
Forwarding                    https://xxx.ngrok.io -> http://localhost:8000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

其中 xxx 是每次重開 ngrok 都會隨機產生,而上面這段 https://xxx.ngrok.io 就是你的 webhook url

2.3 Webhook 串起來

先把 https://xxx.ngrok.io 這串複製下來,再回到瀏覽器的 Line Developer 的 Channel 頁面Messaging API分頁Webhook url 欄位,你會發現為什麼我在後面加了 /line/ 的結尾,因為我們要把 line chatbot 這功能分開,成為這個 server 的一部分,這就是開 API 的藝術的部分了,雖然我這個 API 也沒有開的多好 XD

https://ithelp.ithome.com.tw/upload/images/20200306/20124548ylSba9qgyr.png

所以現在 line 會想辦法傳訊息到 https://xxx.ngrok.io/line/, 但目前我們的 django server 還沒開好,也還沒把 line/ 的 API 開出來,所以下階段就來做 django 的部分吧。

3. 實作 Django Server 來跟 LineBot 對接 !

3.1 在虛擬環境中,安裝 Line-Bot-SDK

(venv)$ pip install line-bot-sdk

補充說明,怎麼在 PyCharm IDE 隨著虛擬環境所安裝的套件變化:
也就是說,PyCharm 怎麼知道我安裝了某某套件 ?
.
答案: 在 PyCharm 的 FileSettingsProject: xxxProject Interpreter → 點齒輪 → Add...Existing Environment → 選擇你的虛擬環境中的 Python 執行檔

https://ithelp.ithome.com.tw/upload/images/20200306/20124548twuXXEEgT5.png

3.2 把 /line/ 的 API 開出來

linebot/urls.py

from django.contrib import admin
from django.urls import path

from webhook.views import webhook_view

urlpatterns = [
		# 開出 line/ 的 API
		# 接著導到 `webhook` app 的 `views.py`
    path('line/', webhook_view),
    path('admin/', admin.site.urls),
]

經過設定之後,我們就開出了 http://xxx.ngrok.io/line/ 的 API,但實際裡面還沒有功能,現在來想辦法收到從 line 過來的訊息吧。

3.3 處理從 line 過來的訊息

webhook/views.py

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from django.shortcuts import render
from django.http import JsonResponse
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponseBadRequest
from django.http import HttpResponse
from linebot.models import MessageEvent, TextMessage, TextSendMessage
from django.conf import settings
import os, time

# 呼叫 `crawler` app 的 `crawl_subscribes_of_youtuber` function
# 這部分已經在 day24 做好,參考 https://ithelp.ithome.com.tw/articles/10230271
from crawler.views import crawl_subscribes_of_youtuber

# 等等要在 `linebot/settings.py` 新增:
# ACCESS_TOKEN 和 CHANNEL_SCRET 兩個變數
line_bot_api = LineBotApi(settings.LINE_ACCESS_TOKEN)
handler = WebhookHandler(settings.CHANNEL_SECRET)

# 接收從 `linebot/urls.py` 傳過來的 request 物件
@csrf_exempt
def webhook_view(request):
		# 解析 request 的 header 是否包含 Line 的簽名
    signature = request.headers["X-Line-Signature"]
		
		# 以 UTF-8 編碼來解析 request body
    body_decode = request.body.decode('utf-8')

    try:
				# 導到 handler 來處理從 line 傳過來的訊息
        handler.handle(body_decode, signature)
    except InvalidSignatureError:
        return HttpResponseBadRequest
    return HttpResponse("OK")


# 實際處理從 line 過來的訊息的地方
@handler.add(event=MessageEvent, message=TextMessage)
def handle_message(event: MessageEvent):
		# 呼叫 `crawler/views.py` 內
		# 的 `crawl_subscribes_of_youtuber` function
    result = crawl_subscribes_of_youtuber(event.message.text)

		# 將爬蟲的結果,以 Line 純文字的訊息,回傳回去給使用者
    line_bot_api.reply_message(
        reply_token=event.reply_token,
        messages=TextSendMessage(text=result)
    )

3.4 透過 token 和 secret 向 Line 驗證身份

settings.py

...
LINE_ACCESS_TOKEN = "xxxxxxxxxxx...xxxxxxx"
CHANNEL_SECRET = "yyyy...yyyy"
...

這兩個變數,可以從 Line Channel 的 Messaging API 裡的 Channel access token 找到;還有從 Line Channel 的 Basic SettingsChannel secret 找到。

https://ithelp.ithome.com.tw/upload/images/20200306/20124548YW8XN0TmIj.png

https://ithelp.ithome.com.tw/upload/images/20200306/20124548B8wvXRJ9W1.png

到這邊,Django 的部分已經結束了

3.5 Django 跑起來 !

(venv)$ python manage.py runserver 127.0.0.1:8000

(因為我們的 ngrok 是開在 8000,所以在跑 django 的時候,還是指定 port 比較保險)

4. 結果

https://ithelp.ithome.com.tw/upload/images/20200306/20124548jGfDkod0Nd.jpg

做到這邊,應該要可以通了,如果沒有,那回去確認每個環節有沒有出錯,可能出錯的環節會有

  • webhook 沒串起來: ngrok 沒啟動、Line Channel 的 Webhook 沒正確設定
  • crawler app 的 code 有錯
  • django 的 line/ API 沒有成功導向 webhook/views.py
  • django 的各類設定(settings.py): allow_hostsinstalled_appacesstokenchannel secret
  • django 沒有跑起來
  • 網路沒通、我講得太爛了QQ

單日心得總結

要把實作的細節重現,還有用稍微白話一點的語句,來解釋每一個動作,真的很花時間,還以為可以在空出更多時間做其他事,沒想到我錯了 QQ

有人可能會想問我為什麼不放到 Heroku,其實我一開始就是放 Heroku,可是放上去之後,爬蟲被防火牆擋住了,可能是太多人把爬蟲放到 Heroku,直接被當成黑名單之類的,後來改放 GAE 就沒問題可以直接跑。

老話依舊,這篇文章沒有詳細到,可以讓第一次接觸的人們,直接照著我的步驟完成,其中隱藏了一些繁瑣的細節觀念,但可以給閱讀的你們實作的大方向,希望對你們有幫助,如果需要各項細節可以留言告訴我。

阿,這禮拜假日放假兩天XD

我是 RS,這是我的 不做怎麼知道系列 文章,我們 下週一見。


https://ithelp.ithome.com.tw/upload/images/20200219/20124548meDsnCPamL.png


1 則留言

0
jacky70638
iT邦新手 5 級 ‧ 2020-10-28 10:55:05

請問如何定義機器人的回覆

我要留言

立即登入留言