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

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

(這一篇還沒有要上架到 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 來架聊天機器人囉~

1.1 反正最後應該要長這樣 XD

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

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

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

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

2. 把 linebot 串到自己的 django server

這句話的意思是

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

2.1 怎麼個串法 ?

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

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)

1
2
3
4
5
6
7
8
9
10
11
12
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

所以現在 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 執行檔

3.2 把 /line/ 的 API 開出來

linebot/urls.py

1
2
3
4
5
6
7
8
9
10
11
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/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

1
2
3
4
...
LINE_ACCESS_TOKEN = "xxxxxxxxxxx...xxxxxxx"
CHANNEL_SECRET = "yyyy...yyyy"
...

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

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

3.5 Django 跑起來 !

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

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

4. 結果

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

  • 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 就沒問題可以直接跑。

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

你可能有發現:「怎麼這篇的標題有編號 ?」,因為我最近在整理我散落在各處的檔案,覺得資料電子化後,如果還是用舊有思維去管理,一樣會很亂,所以需要一些整理方法,讓資料更容易找到,所以就參考了 Esor 大大的 Google 雲端硬碟檔案整理技巧總集,四個高效率的管理邏輯 | 電腦玩物 命名編號方法。雖然 markdown 本來就有 h1、h2、h3 的分層架構,可是文字的大小差異還是不直覺,加上大標的編號就非常清楚明瞭。

我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。


  • 喜歡我的文章嗎? 趕快來看看我都發了什麼文章吧:我的文章目錄
  • 歡迎閱讀我的上一篇: (番外篇-爬蟲)[不做怎麼知道系列之Android開發者的30天後端養成故事 Day24] - 來問問你認識的Youtuber的訂閱數吧~ #crawler #python #socialblade
  • 歡迎閱讀我的下一篇: 待續
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2021-2022 Sam Ho
  • Visitors: | Views:

請我喝杯咖啡吧~

支付宝
微信