【#codeforgender性別駭客工作坊】

Line Bot 教學工作坊 - part 2

Pyladies Taiwan x 女人迷

Speaker : Mars

2017/08/13

Roadmap

  • 基礎應用 08/06
    • 第一個Python程式
    • 字串與物件
    • 判斷式
    • 串列
    • 隨機
    • Line Bot Message Type
  • API的使用 08/13 <===
    • 字典與json
    • Google Maps API
    • api.ai
  • 宣告的時候要加上 LocationMessageLocationSendMessage
    from linebot.models import (
      MessageEvent, TextMessage, TextSendMessage,
      LocationMessage, LocationSendMessage,
    )
    
  • Location Handler

    @handler.add(MessageEvent, message=LocationMessage)
    def handle_location_message(event):
      now_lat=event.message.latitude
      now_lng=event.message.longitude
    
      reply = "現在位置:緯度{},經度{}".format(now_lat,now_lng)
    
      line_bot_api.reply_message(
          event.reply_token,
          TextSendMessage(text=reply)
      )
    

申請Google Places API

建立 Google API 金鑰

API 管理員 > 憑證 > 建立專案 > 建立憑證 > API 金鑰 > 複製金鑰> 關閉

啟用 Google 各服務 API

資料庫 > Google Maps API > 更多 > Google Places API Web Service > 啟用

從文件中找找看,

  • 哪個URL格式是「找尋鄰近地點」?
  • 需要傳進去的參數是?

這個回傳格式叫做json,一種資料交換格式的語言,
但在解析之前,大家觀察一下Google Place API回傳的資料,

還記得上禮拜教的串列是以什麼符號取索引嗎?
這次出現了新的符號{}
我們先來介紹Python中同樣也使用{}的「字典」

字典 dict

  • 鍵值key:很像是串列的索引,
  • 設定值:字典名稱[key]=value
  • 拿取值:字典名稱[key]
  • key:value
    {
      "the":10 ,
      "a"  :9  ,
      "of" :6  ,
      "in" :6
    }

!注意

  • 字典是「非有序」的資料型別
  • 字典是存key,然後以key去找資料value
In [1]:
my_dict = {}
my_dict["the"] = 10
my_dict["a"] = 9
my_dict["of"] = 6
my_dict["in"] = 6
my_dict2 = {"the":10,"a":9,"of":6,"in":6}
print (my_dict)
print (my_dict2)
print (my_dict["the"])
{'the': 10, 'in': 6, 'of': 6, 'a': 9}
{'the': 10, 'in': 6, 'of': 6, 'a': 9}
10

!注意

  • 直接使用字典不存在的key去找資料會有錯誤!
In [2]:
my_dict = {"the":10,"a":9,"of":6,"in":6}
print ("with" in my_dict)
print (my_dict["with"])
False
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-2-bfa4e840c783> in <module>()
      1 my_dict = {"the":10,"a":9,"of":6,"in":6}
      2 print ("with" in my_dict)
----> 3 print (my_dict["with"])

KeyError: 'with'

json 解析

  • json.loads(字串):json格式字串 -> python字典型態
  • json.dumps(字典):python字典型態 -> json格式字串

輔助工具:Json Parser Online

右鍵>檢查>Network

In [3]:
import requests
import json
url = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=女人迷樂園&key=你的金鑰"
rep = requests.get(url) # 回傳的Response物件,包含Header、網頁原始碼
html = rep.text         #      Response物件,網頁原始碼的部分
json_data = json.loads(html)
print (json_data['predictions'][0]['description'])
台灣台北市大安區和平東路二段女人迷樂園 womany wonderland

網路爬蟲就是這樣運作的喔!
有興趣可以參考PyLadies之前「從0到1的網頁爬蟲」活動01~07的投影片:

Coding Time

以女人迷樂園進行地點搜尋
試試看以python解析附近的第1個地點的

  • 名稱
  • 地址
  • 經緯度座標

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=25.025315,121.5295463&key=你的金鑰&rankby=distance&types=police&language=zh-TW

  • rankby=distance:以距離排序
  • types=police:限制回傳地點類型為警察局(地點類型)
  • language=zh-TW:以繁體中文回傳資訊
In [4]:
import requests
import json
url = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=25.025315,121.5295463&key=你的金鑰&rankby=distance&types=police&language=zh-TW"
rep = requests.get(url)
html = rep.text
data = json.loads(html)
first = data['results'][0]
title = first['name']
print (title)
和平東路派出所

Coding Time

與 Line 的 LocationSendMessager 結合,找尋附近的警察局

API keys

In [7]:
import requests
import json
session_id ="COPY CURL"
client_ac = "Client access token"

url = "https://api.api.ai/v1/query?query={}&lang=zh-TW&sessionId={}".format("我有問題",session_id)
header={
    "Authorization":"Bearer {}".format(client_ac)
}
rep = requests.get(url,headers=header)
html = rep.text
print (html)
{
  "id": "9f8df4b5-46ba-41d9-affc-27b69d8913b4",
  "timestamp": "2017-08-13T02:40:33.175Z",
  "lang": "zh-cn",
  "result": {
    "source": "agent",
    "resolvedQuery": "我有問題",
    "speech": "請問你想找哪裡的資訊?",
    "action": "",
    "parameters": {
      "help": "問題",
      "POI": ""
    },
    "metadata": {
      "inputContexts": [],
      "outputContexts": [],
      "intentName": "Ask for help",
      "intentId": "5c9ef3c0-cd86-4bc8-9333-2004bb9997fd",
      "webhookUsed": "false",
      "webhookForSlotFillingUsed": "false",
      "contexts": [
        "5c9ef3c0-cd86-4bc8-9333-2004bb9997fd_id_dialog_context",
        "ask_for_help_dialog_params_poi",
        "ask_for_help_dialog_context"
      ]
    },
    "score": 1.0
  },
  "status": {
    "code": 200,
    "errorType": "success"
  },
  "sessionId": "8874573d-ad1f-43e1-bb20-8d00e8a0b9a8"
}

Coding Time

在與 Line Bot 串接前,
先想想看我們的流程是什麼?

  • 想要找到警察局
  • 要知道使用者的意圖是要找到警察局,也要拿到使用者的位置
  • 使用者的意圖
    => 處理 TextMessage 的 handler
    => 引導使用者說出地點及意圖
  • 使用者的位置
    => 處理 LocationMessage 的 handler
    => 如果沒有使用者位置,引導使用者說出地點

Q&A 時間

如何dubug

  • 透過heroku的log介面
  • Google大神->StackOverflow
  • FB社團、提問的智慧

想要幫Bot加上更多功能

  • 想要知道如何從其他網站抓資料傳送到LINE裡 EX:PPT

    • 如同用requests抓取api的資料一樣,
      但因為網站的格式不像api回傳的是乾淨的json,需要額外解析(ex.BeautifulSoup、lxml)
    • 可以參考 twtrubiks 寫的 Line Bot
  • bot可以自己學習尚未辨認的字串

想要幫Bot加上更多功能 PyLadies宣傳時間xD

  • 哪裡還可以學習講師的課程?

    • 請關注 PyLadies 粉絲團,九月中開始會有一系列給新手、老手的活動
    • 主辦限女性,合辦以主辦方為準,依照講師意願開放投影片
  • 希望可以學到自己用flask開RESTful API

  • 自動讀取圖檔上的文字並分類

    • 讀取圖檔上的文字:pytesseractGoogle Vision API
    • 分類:sklearn、Deep Learning
    • (主辦)在十二月會由Mosky帶領「Practicing Data Science with Python」

其他Bot與學習資源

  • 這次寫的code是否可以轉移用在messenger bot

    • 因為各家Bot的規格不同,所以是無法完全轉移的,
      但同樣都是Flask框架,還有Python語法、串接api的部分是可行的!

    • 可以參考 enginebai 寫的 FB Messenger Bot

  • Bot開發推薦網站