GoとSlackのbotを組み合わせて勉強をしてみたかったので関東の電車運行状況を取得するbotをつくってみました。
本当は勝手につぶやく方式にしたかったのですがとりあえずこの時点で記事にします。
(そのうち改造するかも。)
Slack Appの作成
こちらのサイトを参照し作成しました。
GolangでSlack Interactive Messageを使ったBotを書く
botの作成
スクレイピングするパッケージのインストール
goqueryをインストールします。
jQuery的な操作が出来るので経験のあるWebエンジニアには割とすんなり理解できます。
$ go get github.com/PuerkitoBio/goquery
情報を取得するWebサイト
こちらがないと始まりません。
今回はYahoo!路線情報さんから取得します。
実装
では実際にコーディングしてアプリをつくります。
「運行状況」というキーワードに反応して上記サイトから運行状況を返すbotです。
package main
import (
"log"
"os"
"net/url"
"github.com/nlopes/slack"
"github.com/PuerkitoBio/goquery"
)
// HTMLをスクレイピングして運行状況のテキストを取得する
func getRailwayText() string {
_url := "https://transit.yahoo.co.jp/traininfo/area/4/"
doc, err := goquery.NewDocument(_url)
if err != nil {
panic(err)
}
u := url.URL{}
u.Scheme = doc.Url.Scheme
u.Host = doc.Url.Host
var message string
// まずはテーブル要素を取得する
doc.Find("div.trouble > table > tbody").Each(func(_ int, s *goquery.Selection) {
// 次にtrを掘っていく
s.Children().Each(func(idx int, ss *goquery.Selection) {
// idx==0は見出し列なので飛ばす
if (idx > 0) {
railway := ss.Children().Find("a").Text()
status := ss.Children().Find("span.colTrouble").Text()
detail := ss.Children().Next().Next().Text()
message = message + status + " @ " + railway + " (" + detail + ")\n"
}
})
})
return message
}
func run(api *slack.Client) int {
rtm := api.NewRTM()
go rtm.ManageConnection()
for {
select {
case msg := <-rtm.IncomingEvents:
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
log.Print("Hello Event")
case *slack.MessageEvent:
switch ev.Text {
case "運行状況":
message := getRailwayText()
rtm.SendMessage(rtm.NewOutgoingMessage(message, ev.Channel))
case "help":
rtm.SendMessage(rtm.NewOutgoingMessage("Usage: 運行状況 関東圏の電車の運行状況を表示します。\n 他の機能?ないよ。", ev.Channel))
}
case *slack.InvalidAuthEvent:
log.Print("Invalid credentials")
return 1
}
}
}
}
func main() {
api := slack.New("YOUR TOKEN")
os.Exit(run(api))
}
トークンはSlack APIページの左メニュー[OAuth & Permissions]の[Bot User OAuth Access Token]にあります。
実行
ではローカルのターミナル上で動かしてみます。
$ go run slack_bot.go
2019/05/03 11:03:27 Hello Event
Hello Eventが表示されれば成功です。
実際につくったbotに対してメッセージを送ってみます。
ちゃんと返ってきました!
終わりに
goqueryは欲しいオブジェクトの検索条件を指定するだけで勝手にとってきてくれるので非常に便利でした。
複数のサイトから情報を取得する場合であってもGoお得意の並行処理で効率的に処理したりできそうですね。
slack-botも拡張性が高く、工夫次第で様々なところで効率化ができそうです。