Amazon Echoにバスの到着時刻を教えてもらう(関東バス編)


はじめに

この記事は、osa9さんの「Amazon Echoにバスの到着時刻を教えて貰う」をパクり改変したものです。
元記事は小田急バスでしたので、自分用に関東バス版へ変更しています。

完成したコード

alexa_bus.py
import logging
import urllib.request
from bs4 import BeautifulSoup

# 関東バスのリアルタイム運行状況のURL(サンプルは中野駅 → 江古田駅)
BUS_SCHEDULE_URL = 'http://www2.kanto-bus.co.jp/blsys/navi?VID=ldt&EID=nt&DSMK=74&DK=2a_1ev_2d-2a_1ev_a1-2a_1ev_2f-2a_1ev_ie-2a_1ev_2h-2a_1ev_2vbp85'


# 関東バスのリアルタイム運行状況を取得する
def get_bus_schedule(url):
    logging.info("Retrieving URL: {}".format(url))
    content = urllib.request.urlopen(url).read().decode('shift_jisx0213')
    soup = BeautifulSoup(content, "html.parser")

    # エラーメッセージがある時(バスが終了している時も含む)
    errors = soup.select('.errorTxt')
    if len(list(errors)) > 0:
        message = errors[0].contents[0]
        logging.warn("Error: ".format(message))
        raise Exception(message)

    # ダイヤをパースする
    result = []
    for bus_info in soup.select('.outputResult tr')[1:]: # 最初の<tr>はタイトルなので除外する。
        res = list(map(lambda col: col.string, bus_info.find_all('td')))

        # のりば名が無いパターンの時(のりばが一個しか無い時等)
        #if len(res) == 6:
        #    res = res[:2] + [None] + res[2:]

        info = {
            'scheduled_arrival': res[0],  # 時刻表上の到着時刻(ex 10:00)
            'bus_stop': res[1],  # 乗り場 (ない時はNone)
            'bus_route': res[2],  # 系統 (ない時はNone)
            'destination': res[3],  # 行き先 (ex 中野駅)
            'type': res[4],  # 車両 (ex ノンステップ)
            'status': res[5]  # 運行状況 (ex 約5分で到着します。, まもなく到着します)
        }

        result += [info]

    return result


def bus(event, context):
    logging.info(event)

    # もしバス停名を指定したければ使う
    # busStopName = event['request']['intent']['slots']['BusStop']

    # スケジュールを取得してメッセージを組み立てる
    try:
        schedules = get_bus_schedule(BUS_SCHEDULE_URL)
        message = '{}行きのバスは{}'.format(schedules[0]['destination'], schedules[0]['status'])
        if len(schedules) > 1:
            message += 'その次は{}'.format(schedules[1]['status'])
    except Exception as e:
        message = 'エラー {}'.format(e.message)

    logging.info(message)

    response = {
        'version': '1.0',
        'response': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': message,
            }
        }
    }

    return response


# テスト用
if __name__ == '__main__':
    print(bus(None, None))

基本的にコードはほぼ元のままです。
運行情報が記載してあるWEBページの構成が異なるので、ページに合うよう修正しています。

スキルの作成

AWSの画面レイアウトが古いですが下記の記事が参考になります。
※ランタイムが「Node.js 6.10」になっているので、「Python3.6」変更してください。

ハマッたところ

BeautifulSoupのパッケージもLambdaにアップする必要があった。

実行したら、BeautifulSoupのパッケージがないのでエラーになりました。
下記の記事が参考になります。
【AWS】Lambdaでpipしたいと思ったときにすべきこと - Qiita

ハンドラの名前を間違えた

「ファイル名.動かす関数名」なので、「alexa_bus.bus」とすべきところを、「alexa_bus.get_bus_schedule」としていました。

設定値

インテントスキーマ
{
  "intents": [
    {
      "intent": "busTimeIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    }
  ]
}

インテント名は"busTimeIntent"としました。

対話モデル
busTimeIntent バスの時間を教えて
busTimeIntent バスはいつ来る
busTimeIntent 次のバスは

対話モデルにはそれっぽい文章を設定します。

Amazon Echoで動かす。

Amazon開発者アカウントとEchoでログインしているアカウントが紐付いていれば、Skillに開発中のスキルが表示されるので、公開手続きは不要でそのまま使えます。

「Alexa, 時刻表を開いて、次のバスは?」
「中野駅行きのバスは約3分で到着します(3つ前を出ました)。その次は約15分で到着します」

参考にした記事