【祿】邁向財務「自由」之路 II — 育成收發 Telegram 的智能秘書(下篇)

本篇繼續我們開發收發 Telegram 短訊彙報牛記匯率的智能秘書之旅!由於這兩篇的技術含量較高,如果讀者是初次接觸編程,建議由上篇或者系列第一篇 Google Sheet 智能秘書開始閱讀。



上回講到我們已從牛記匯率網頁擱取到所有外幣的匯率,並儲存在一個名叫 FXDatabase 的 Python 字典物件內。本篇我們會討論:

  • 資訊的展現,即如何將 FXDatabase 內的資訊,換成秘書在 Telegram 發送的訊息;
  • 利用另一個 Python 程序,將已開發的程序跟 Telegram 聯繫,建立聊天機械人(Chatbot);
  • 將程序放上雲端運算,讓程序 24/7 執行,讓智能秘書隨時隨地為你效勞。

我們會討論兩種訊息: (1) 發送主要貨幣的匯率一覽,以及 (2) 根據我們輸入的貨幣代碼,回覆相應貨幣的匯率。


4. 以喜歡的形式  將字典裏的資訊換成短訊息

這個步驟是整個開發過程中最開心、最自由度大、最考創意的,因為我們可以通過資訊的展現,決定私人智能秘書的性格、做人物角色設定。當然,性格這回事,並沒有對錯的,喜歡就好 :)

這一步我們先來編寫秘書所回覆的訊息,下一步我們再想如何讓秘書連線上 Telegram,以及秘書如何看懂我們在 Telegram 發出的訊息。

現在假設筆者希望得到的訊息有兩款:

  1. 主要貨幣的匯率買賣價一覽,其中「主要貨幣」自定義為美元、英鎊、歐羅、日圓和人幣。效果如下圖:

  1. 當自己在 Telegram 輸入貨幣的代碼,顯示該貨幣的買賣價。效果如下圖:


為了方便 Telegram 程序的存取,我們將所需要的訊息寫成是函數的回傳。待會我們就能看到這個方法的好處——利用函數直接得到所需要的訊息,而不用將製作訊息和顯示訊息的程式碼混在一起。

在此之前,讓我們也先把上回得到 FXDatabase 的程序,以函數形式表示:

   def DownloadFXDB():
       r = requests.get(url).content
       Soup = BeautifulSoup(r, "html.parser")
       TargetRows = Soup.find("table").find_all("tr")[2:]

       FXDatabase = {}

       for Row in TargetRows:
           Currency = Row.find_all("td")[1].text.encode('utf-8')
           TDBuy = Row.find_all("td")[2]
           TDSell = Row.find_all("td")[3]
           Buy = GetFX(TDBuy)
           Sell = GetFX(TDSell)   
           FXDatabase[Currency] = { 'Buy' : Buy, 'Sell' : Sell }
    
       return FXDatabase

這樣每次呼叫 DownloadFXDB,Python 就會從網際網路下載最新的牛記匯率,並製作匯率字典了。


4a. 回傳訊息內容函數:主要貨幣的匯率買賣價一覽

第一行當然是定義一個函數:

   def MajorCurrFXMsg():

在函數中,首先讓我們從網際網路下載最新的匯率資訊:

   FXDatabase = DownloadFXDB()

然後,告訴 Python 我們需要的主要貨幣列表:

   MajorCurr = ['USD','GBP','EUR','JPY','RMB']

接下來,由於我們也是用 for 迴圈去累積訊息的內容,所以也得先建立一個空字串:

   Message = ""

當然,如果想為私人秘書加添一些個人性格,可以在這一步加上⋯⋯

  • 通告風: Message = "💹 主要貨幣匯率一覽" + "\n"
  • 客服風: Message = "👩🏻‍💻 以下是為尊貴閣下從網路實時取得的匯率報價" + "\n"
  • 女僕風: Message = "💁🏻‍♀️ 主人,這是您需要的匯率資訊 ☺️" + "\n"
  • 外星生物風: Message = "👽 本星球列強貨幣等價 🌍" + "\n"

其中 "\n" 是換行符號。

來到靈魂一步,寫一個 For 迴圈,將所有主要貨幣跑一遍,並將匯率資訊以自己喜歡的形式展現出來。這裏筆者只展現基本形式:

   for Currency in MajorCurr:
       Message = Message + Currency + " 買 " + 
                 str(FXDatabase[Currency]['Buy']) + " 沽 " + 
                 str(FXDatabase[Currency]['Sell']) + "\n"

其中 str() 函數是將匯率數字變成字串便於與訊息其餘部份連繫在一起。最後將 Message 作為函數的回傳:

return Message




4b. 回傳訊息內容函數:按照輸入顯示該貨幣匯價

假設使用者在 Telegram 輸入的貨幣代號名稱為 InputCurr (我們將在下節討論智能秘書如何接收我們的指令)。我們輸出訊息內容的函數可以直接以此為參數:

   def PromptedCurrFXMsg(InputCurr):

同樣的,我們先下載最新的匯率資訊:

   FXDatabase = DownloadFXDB()

然後在顯示匯率資訊之前,讓我們先檢查輸入的代號是否存在在從牛記取得的字典內。要取得 FXDatabase 內所有貨幣,亦即該字典的「索引」列表,方法是 .keys():

   if InputCurr not in FXDatabase.keys():
       Message = "對不起,沒有提供" + 
                 InputCurr.encode('utf-8') + "的匯率"

如果存在,則顯示相應的匯率:

   else:
       Message = InputCurr.encode('utf-8') + " 買 " + 
                 str(FXDatabase[InputCurr]['Buy']) + " 沽 " + 
                 str(FXDatabase[InputCurr]['Sell'])

   return Message

留意筆者在 InputCurr 用上了 .encode('utf-8'),這是因為使用者從 Telegram 輸入的訊息,也會被視之為 UTF-8 編碼的。




4c. 小結

至此,整個輸入輸出匯率的程序碼檔 NgauKeeFX.py 已開發完成。整個檔案應該有四個程序函數(內容從略):

   ## NgauKeeFX.py

   import requests
   from bs4 import BeautifulSoup

   def GetFX(TD):
       ...

   def DownloadFXDB():
       ...

   def MajorCurrFXMsg():
       ...

   def PromptedCurrFXMsg(InputCurr):
       ...


5.  建立 Telegram 聊天機械人  並將已開發的程序聯繫

說到底,我們的 Telegram 智能秘書就是一個聊天機械人(Chatbot)。我們現在就要建立一個新的 Chatbot,並以 Python 程序賦予這個 Chatbot 靈魂。

5a. 建立一個新 Chatbot

要建立一個新的 Telegram Chatbot,我們得去拜訪眾 Bot 之父 —— BotFather。(你猜對了!BotFather 本身就是一個 Bot。)要把他加進你的 Telegram 通訊表,網址是:


BotFather 能給你清晰的指示如何建立和管理你的聊天機械人(們)。例如,要建立一個新的聊天機械人,可以輸入「/newbot」指令(或直接按 BotFather 訊息上的相關連結),並按指示先後輸入顯示名稱(日後可更改)以及系統名稱(日後不可更改,並需以 bot 字結尾):



BotFather 會給予這個新 Bot 一個 Token,請務必妥善儲存及處理,因為不幸落入別人手中,別人就能騎劫你的秘書。

現在我們也可以利用「/setuserpic」指令,為秘書助理上載一幅個人玉照:


效果如下圖:


是否已經很有血肉的真實感覺了?且慢,現在我們的 Telegram Chatbot 還需要你為他/她賦予智慧,就是那顆有能力跟你對答的靈魂,而這就是本篇的重點所在。

5b. 為 Chatbot 賦予靈魂

Telegram 本身提供以 HTTP 為基礎的 API,所以要賦予 Telegram Bot 靈魂可以有很多方法,Python、JavaScript,甚至 Excel VBA 也可以,只要讀者能找到這些程式語言如何與 Telegram 提供的 API 溝通便可。

本篇筆者將會利用一個蠻好用的 Telegram API 的 Python Wrapper「Python Telegram Bot」。而為避免本文成為一篇真正的「宅文」,太技術性的部分筆者在解釋上或會有所從略。各位編程員如有興趣,可以拜讀其 GitHub 介紹:https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API

要使用這個 Wrapper,第一件事當然是安裝進系統(Google Colab 的朋友這回對不起了,Google 還沒有支援,所以請還是回到 Terminal 去⋯⋯):

$ pip install python-telegram-bot --upgrade

接著,讓我們新增一個靈魂程式碼檔 TelegramBot.py,並將之放在與 NgauKeeFX.py 同一個資料夾內。第一句我們從 Python Telegram Bot 匯入需要的部件:

   from telegram.ext import Updater, CommandHandler, MessageHandler, Filters

還有要匯入的當然是擱取匯率資訊的自家建設的函數群:

   import NgauKeeFX

接下來幾句,筆者先不作解釋,請照著打就好;除了 Token 的位置,請換上 BotFather 親授閣下的智能秘書 Chatbot 的私人 Token(字串格式)。

   Token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
   updater = Updater(token=Token)
   dispatcher = updater.dispatcher

至此準備功夫已做好了。接下來就可以即席揮毫,就著使用者所有可能的輸入,逐一書寫智能秘書的回應!

首先,有否留意在上面截圖中,當跟新的智能秘書打招呼時,系統會強制執行一個叫做 /start 的指令?這個是讓智能秘書跟你 Say 個 Hi 的機會。上圖中的秘書尚未有反應,就是因為他/她的靈魂還沒有裝上。要編寫智能秘書在你給予 /start 指令的反應,可以新增以下幾句:

   def start(bot, update):
       Message = "福祿壽全兄您好!很高興能為您效勞!"
       bot.send_message(chat_id=update.message.chat_id, text=Message)
   start_handler = CommandHandler('start', start)
   dispatcher.add_handler(start_handler)
   updater.start_polling()


現在,我們可以呼喚一下這個小小靈魂,讓它叫動我們的智能秘書了!儲存好 TelegramBot.py 之後,在 Terminal 移動到放有兩個 .py 檔案的資料夾,然後執行:

   $ python TelegramBot.py

接著在 Telegram 試著再次開展跟秘書的對話。神奇的事… 就… 此… 發… 生…



不過這個時候如果我們向秘書發送其他的訊息,他/她還是會木頭木腦毫無反應的;這就要靠我們後續的努力了!另外,留意 Python 程序仍然在執行以不斷接收並處理使用者的輸入,一但我們中止了程序(Mac Terminal 可按 control + z)或是把電腦關掉,秘書的靈魂就會熄滅掉。這就是我們最後一步需要考慮將靈魂放上雲端運算的原因。


下一步就是牛記匯率的問答。我們希望秘書能回應「/fx」的指令。如果指令後有其他參數,將參數視為所需貨幣,並嘗試按照輸入顯示該貨幣匯價;否則就視指令為顯示主要貨幣的匯率買賣價一覽。輸入如下並再執行靈魂程式:

   def FX(bot, update, args):
       Currency = " ".join(args)
       if Currency == "":
           Message = NgauKeeFX.MajorCurrFXMsg()
       else:
           Message = NgauKeeFX.PromptedCurrFXMsg(Currency)
       bot.send_message(chat_id=update.message.chat_id, text=Message)

   fx_handler = CommandHandler('FX', FX, pass_args=True)
   dispatcher.add_handler(fx_handler)


建構一個 Chatbot 是否要比想像中簡單?

再來下一段,就是如果用家不是用「/fx」指令的方式提出要求,我們還是盡量希望能配合的。如果用家能輸入「FX」、「匯率」、「牛記」等字眼,我們也會視之為對牛記匯率的請求,顯示主要貨幣的匯率買賣價一覽。否則,我們的秘書還是會禮貌地(或不禮貌地,視乎讀者對其角色設定)告訴使用者自己看不明白:

   def echo(bot, update):
       if update.message.text.encode('utf-8') in ["FX","匯率","牛記"]:
           Message = NgauKeeFX.MajorCurrFXMsg()
       else:
           Message = "福祿壽全兄,恕我未能明白何謂「" + 
                     update.message.text.encode('utf-8') + "」。"
       bot.send_message(chat_id=update.message.chat_id, text=Message)
   echo_handler = MessageHandler(Filters.text, echo)
   dispatcher.add_handler(echo_handler)

告訴使用者自己看不明白,除了訊息外,同樣適用於看不明白的指令:

   def unknown(bot, update):
       Message = "福祿壽全兄,恕我未能明白何謂「" + 
                  update.message.text.encode('utf-8') + "」。"
       bot.send_message(chat_id=update.message.chat_id, text=Message)
   unknown_handler = MessageHandler(Filters.command, unknown)
   dispatcher.add_handler(unknown_handler)




5c. 小結

至此,整個控制智能秘書的靈魂程序碼檔 TelegramBot.py 也開發完成。整個檔案應該有四個程序函數及其相應新增至 Handler 及 Dispatcher 之指令(內容從略):

   ## TelegramBot.py

   from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
   import NgauKeeFX

   Token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
   updater = Updater(token=Token)
   dispatcher = updater.dispatcher

   def start(bot, update):
       ...

   def FX(bot, update, args):
       ...

   def echo(bot, update):
       ...

   def unknown(bot, update):
       ...


如果讀者打算長開個人電腦,為秘書提供永恆的靈魂,以下的最後一步可以省略。否則,請繼續完成最後一節……


6.  將智能秘書的靈魂程式放上雲端運算

網上支援 Python 雲端運算的服務可謂包羅萬有,從山寨免費服務到企業級的 Google Cloud Platform / Amazon AWS 都有,豐儉由人,讀者不妨多做比較再決定讓秘書的靈魂在何處落地生根。

筆者選用的是 Python Anywhere (https://www.pythonanywhere.com),貪其方便易用,系統 Up Time 和穩定性也不錯。網站雖然容許免費戶口,但免費戶口能「瀏覽」的只限此表(https://www.pythonanywhere.com/whitelist/)註明的網站;要擱取牛記匯率等特定網站,筆者用的是最低級的收費戶口,每個月美帝幣 5 枚。

開戶後,在 Files 新增一個資料夾(假設叫「TelegramBot」),並把 NgauKeeFX.py 及 TelegramBot.py 上載至資料夾內。

在 Consoles 新增一個 Bash(就是 Terminal / Command Prompt)。在執行靈魂程序 TelegramBot.py 之前,別忘了安裝我們會用到的 程序包。注意 Python Anywhere 支援不同版本的 Python,我們用到的是 2.7,所以應利用 「pip2.7」;另外我們只有替自己而沒有替其他用家安裝的權限,所以亦需註明「--user」:

   $ pip2.7 install --user requests
   $ pip2.7 install --user beautifulsoup4
   $ pip2.7 install --user python-telegram-bot --upgrade

之後便可以執行靈魂程序,其中 username 是閣下 Python Anywhere 的用戶名稱:

   $ python TelegramBot/TelegramBot.py

這就完成將秘書靈魂放到網路雲端處運算的工序了。

留意理論上靈魂程序的執行是不會自己終止的,但雲端伺服器偶爾也會有維護而強行殺掉靈魂的時候。Python Anywhere 提供了一個繞路方案,讓程序保持接近 24/7 執行,詳情可以參考:https://help.pythonanywhere.com/pages/LongRunningTasks

設定好後,靈魂程序便能(接近) 24/7 執行,讓智能秘書隨時隨地為我們效勞了!



總結

前後花了兩個月時間才將這幾個月來學到的技巧整理成文,雖然愈寫愈覺得是在「趕客」,希望仍然對某部份理科底子比較強的讀者群、有興趣研究自動化、以及以最皮毛的方式初窺一下下一波「中年危機」即人工智能如何取代我們飯碗的朋友,有所裨益和幫助吧!

書於山竹襲港全城戒備的十號風球前夕,明天既然大家都只能待在家裏,何不一起動手來,在 Telegram 砌個虛擬男女朋友 / 閨蜜 / 颱風預報科學主任,甚至懂報股價和分析股票的大師? 



熱門文章