用Python和Twilio打造SMS簡訊機器人

七月 19, 2017
Facebook
Twitter
圖片

AdobeStock/Kitja

這個冬天,我和朋友們去了一趟猶他州,一起探索了一些世界上最遙遠又美麗的地點。我攀越了類似電影《星際大戰》場景的地形,讚嘆於亮紅色的峽谷。然而,我卻遇上一個難題:由於我們身處於距離都市非常遙遠的地方,手機頂多只能接收到2G訊號。
2G訊號只能傳送文字簡訊,完全沒辦法讀取The Weather Channel的app畫面。有時我們完全沒有任何準備,就必須在雨中或低溫下爬山。這是一件十分惱人的事情。況且這種狀況並不只有在遙遠的地方才會發生。在我學校體育館的更衣室裡,手機通常是沒有任何訊號的。這讓我難以讀取跑步訓練前所需要的資料,例如室外體感溫度。遭遇到這些狀況後,我想要打造一臺能夠提供任何需要資訊、且不需要3G或LTE訊號的專屬簡訊機器人。
PARTS

開始打造機器人

我要用Twilio API和Python來打造這臺能送出Twilio數字訊息並收到回覆的簡訊機器人。儘管這個專題看起來困難重重,但不用擔心!你將學會如何使用命令提示視窗和終端機、如何架設和維護伺服器、以及如何操控字串以在不同API(應用程式介面)之間獲取資料。
Twilio讓你能很容易地安裝任何你需要的東西,而用Python和PIP(一個基於Python語言的封包管理程式)之類的工具則能讓你輕鬆做好架設SMS簡訊伺服器的準備。只要按照下列這些步驟來準備你的程式開發環境,不要被看似繁雜的程式指令給嚇到了。你並不需要完全理解每一個步驟,只要記得正確無誤地照著下列這些步驟來做,所有你需要的東西就會設定好了。
圖片

AdobeStock/lzf

步驟1

首先,既然我們是用Python語言來開發簡訊機器人,你必須先把Python安裝好。為了檢查你的電腦是否以安裝好Python,打開命令提示視窗或終端機,輸入下列指令:
python –version
你應該會收到一串類似「python -2.7.0」之類的電腦回覆。版本編號並不重要。如果你還沒安裝好Python,先安裝吧。網路上有數不清的來源可以安裝這個軟體。

步驟2

安裝好Python後,接下來你會需要PIP,一個基於Python語言的封包管理程式。PIP能讓你輕鬆安裝數不盡的函式庫,包含Twilio。透過PIP,你可以直接在終端機上輸入「pip[封包名稱]」,而不必在網路上一一搜尋所需安裝的SDK。如果你已經是一個Python程式開發者,你應該已經裝好PIP了。如果你不是程式開發者,也不必擔心。
此外,我們還需安裝一個叫做虛擬環境的東西(virtualenv),它能讓我們開啟一個能夠運行特定版本工具的程式。更方便的是虛擬環境還包含了PIP,太棒了!請將虛擬環境想像成一套能將軟體分別區隔到不同電腦沙盒(sandbox)的工具,而當你在使用PIP並且更新不同的封包時,你的程式碼依然能夠正常運作。有時候在寫程式的時候,你會下一些你並不完全了解其功用的指令。Virtualenv便會避免這個狀況造成你的程式崩潰。
要安裝Virtualenv,首先進到你想安裝這個程式的資料夾,然後輸入下列任一組指令,直到你看到Virtualenv開始安裝(這些指令適用於不同版本的Python):
easy_install virtualenv
easy_install-2.7 virtualenv
pip install virtualenv
如果你得到「permission denied」(存取被拒)的訊息,請改為在你的程式碼最前面新增輸入「sudo」,然後輸入你的電腦密碼。接著打開virtualenv開始把我們這個專案要用到的工具安裝到這個「sandbox」。然後當你輸入下面這個指令時,你的終端機上應該會在括號中顯示你的資料夾名稱:
source bin/activate

步驟3

現在我們已經安裝好比Python本身更被廣泛使用的PIP和virtualenv,但為了我們的簡訊機器人專題,我們還需要安裝函式庫:Twilio和Flask。Twilio函式庫讓你能發送和接收簡訊,而Flask讓你能用Python程式來連接本地伺服器。
我們會分別安裝特定版本的函式庫到我們的沙盒(注意在這個階段virtualenv依然在運行),確保我們的程式能夠正常運作。為了能夠一次安裝所有的函式庫,先隨便開一個txt文字檔,然後重新取名為「requirements.txt」。另外為了確保我們安裝了正確的版本,在txt文字檔中輸入:
Flask>=0.8
twilio>=3.3.6

步驟4

最後還有一個軟體要安裝:Ngrok(到這裡下載)。Nrgok在運行的時候,會把我們本地端的程式(我們的程式會透過Flask運行)連結到網路上,然後會提供一個http網址給我們。Twilio會透過這個網址將傳進來的資訊用簡訊傳送給我們。

步驟5

現在所有程式都安裝完成了,就可以開始設定我們的機器人了。到Twilio網站按下「Get a free API key」(獲得免費API金鑰密碼)。創設一個帳號(選擇免費帳號)然後進入主畫面。

步驟6

好了,現在所有我們需要的程式都已安裝完成,可以開始寫程式碼了。在你的作業系統中開啟你最常用的文字編輯軟體(例如Windows記事本),儲存檔案命名為「run.py」(或其他任何名稱),並且輸入以下這些程式碼(我已事先在每一行程式碼旁邊寫出解釋):
# import all the libraries we will be using
from flask import Flask, request
from twilio import twiml

# set up Flask to connect this code to the local host, which will
# later be connected to the internet through Ngrok
app = Flask(__name__)
    
# Main method. When a POST request is sent to our local host through Ngrok 
# (which creates a tunnel to the web), this code will run. The Twilio service # sends the POST request – we will set this up on the Twilio website. So when # a message is sent over SMS to our Twilio number, this code will run
@app.route(‘/’, methods=[‘POST’])
def sms():
    # Get the text in the message sent
    message_body = request.form[‘Body’]
    
    # Create a Twilio response object to be able to send a reply back (as per         # Twilio docs)
    resp = twiml.Response()
    
    # Send the message body to the getReply message, where 
    # we will query the String and formulate a response
    replyText = getReply(message_body)

# Text back our response!
    resp.message(‘Hinn’ + replyText )
    return str(resp)
# when you run the code through terminal, this will allow Flask to work
if __name__ == ‘__main__’:
    app.run()

步驟7

接下來我們要創造一個類似getReply客服中心的功能。這個功能會直接分析我們的簡訊內文,然後弄懂我們想要知道的是哪一類資訊。然後它會在不同API之間搜尋資料,再回傳搜尋結果。假設我們設定文字簡訊內容是「keyword_request」(關鍵字指令)的格式,一個能讓我們在訊息中定義指令內容的簡單格式如下:
# Function to formulate a response based on message input.
def getReply(message):
    
    # Make the message lower case and without spaces on the end for easier handling
    message = message.lower().strip()
    # This is the variable where we will store our response
    answer = “”
    
    if “weather” in message:
        answer = “get the weather using a weather API”
            
    # is the keyword “wolfram” in the message? Ex: “wolfram integral of x + 1”
    elif “wolfram” in message:
 answer = “get a response from the Wolfram Alpha API”
    
    # is the keyword “wiki” in the message? Ex: “wiki donald trump”
    elif “wiki” in message:
 answer = “get a response from the Wikipedia API” 

    # is the keyword “some_keyword” in the message? You can create your own custom  
    # requests! Ex: “schedule Monday”
    elif “some_keyword” in message:
 answer = “some response”

    # the message contains no keyword. Display a help prompt to identify possible 
    # commands
    else:
        answer = “n Welcome! These are the commands you may use: nWOLFRAM “wolframalpha request” nWIKI “wikipedia request”nWEATHER “place”nSOME_KEYWORD “some custom request”n”
    
    # Twilio can not send messages over 1600 characters in one message. Wikipedia
    # summaries may have way more than this. 
    # So shortening is required (1500 chars is a good bet):
    if len(answer) > 1500:
        answer = answer[0:1500] + “…”
    
    # return the formulated answer
    return answer

步驟8

現在我們的訊息內容格式已經設定成:「keyword_request」(關鍵字_指令)。但是你不能在wolfram alpha自動問答系統裡直接輸入「wolfram calories in bread」(wolfram麵包的熱量),不過輸入「calories in bread」(麵包的熱量)是可行的。所以現在我們要把wolfram從訊息中去掉,以把我們下的指令獨立出來。這可以用下列方法做到:
# Function for editing input text. Ex: If you send the message “wolfram calories in bread”, 
# the program will recognize “wolfram” and call this function and will 
# change the text to “calories in bread”, which will then be sent to wolfram.
def removeHead(fromThis, removeThis):
    if fromThis.endswith(removeThis):
        fromThis = fromThis[:-len(removeThis)].strip()
    elif fromThis.startswith(removeThis):
        fromThis = fromThis[len(removeThis):].strip()
    
    return fromThis

步驟9

接下來,是時候將API放進來了。我們會採用Wolfram Alpha, Wikipedia和yWeather這三個API。這些應用程式各自都有很棒的線上資料庫,所以我不會花太多精神在getReply功能裡建立「if敘述」。要使用Wolfram Alpha你必須先到他們的API網站獲取API金鑰。Wikipedia和yWeather則不需要金鑰就能擷取資料。

步驟10

接著來設定Wikipedia API。在電腦終端機裡輸入「pip install Wikipedia」。再到getReply功能裡,找到Wikipedia的if敘述程式碼,加入下列內容:
# is the keyword “wiki” in the message? Ex: “wiki donald trump”
    elif “wiki” in message:
        # remove the keyword “wiki” from the message
        message = removeHead(message, “wiki”)
        
        # Get the wikipedia summary for the request
        Try:
    # Get the summary off wikipedia
            answer = wikipedia.summary(message)
        except:
            # handle errors or non specificity errors (ex: there are many people
     # named donald)
            answer = “Request was not found using wiki. Be more specific?”

步驟11

讓我們用Wikipedia測試一下到目前為止我們的程式碼能不能運作。首先進入電腦終端機,找出你的Python檔案,確認你的虛擬環境正在運行中(輸入「source bin/activate」),然後再輸入「python run.py」來執行你的程式碼。你應該會看到Flask正在執行一系列數字的畫面。把這些連接埠號碼(port number)記起來。我的終端機畫面會長得像下圖這樣,而我的連接埠號碼是5000:
接下來打開另一個終端機視窗並輸入這個指令:「ngrok http [連接埠號碼]」。你應該會看到終端機螢幕變黑:
複製任一個轉址網址。然後到你的Twilio主畫面按下畫面左方的「#」字號。點擊Twilio數字,畫面往下捲動,然後在「A message comes in」欄位裡輸入剛剛複製的網址。另外要確認該選項的下拉式選單設定在「webhook」。
按下儲存。這樣就大功告成了!

步驟12

傳簡訊給你的Twilio號碼,看看你有沒有收到回覆!

結論

現在你已經成功創造了你的專屬SMS簡訊機器人了。你可以讓它一直運作直到天荒地老,也可以照著步驟十一來重新啟動簡訊機器人。而且現在你對程式碼該怎麼寫已經有一個初步概念了,之後你可以按照個人喜好任意加入指令了!
舉例來說,我新增了獲得個人行程和日期的功能。所以當我傳「A day schedule」訊息給我的Twilio號碼時,它就會回傳我的課程表。盡情發揮你的創意,然後盡可能地新增任何你想到的API。只要先閱讀每個API的使用說明文件,通常不會遭遇到太多困難。享受寫程式吧!
(譯:葉家豪)
原文
Social media & sharing icons powered by UltimatelySocial