はじめに
クラウドワークス1年生の@yizknnです。2018年8月にエンジニアとして入社しました。
外部向けに投稿するのは初めてなので部屋の隅で震えながら書いています。
前置き
ある時、先輩がこう仰りました。
「ランチは毎日違うお店に行きたい。エンジニアたる者、未知への探究心を忘れたくない」
そんな訳で、修行も兼ねて社内版OSS Gateの時間を利用して、ランチ候補を調べてくれるbotを作成してみました。
クラウドワークスのOSSへの取り組みは、@minamijoyoさんの記事で詳しく紹介していますので宜しければ併せてご覧ください。
OSS開発に参加してみたい人の背中を押して回る - クラウドワークス エンジニアブログ
どんなBot?
GitHub: https://github.com/yizknn/slack-lunch-bot
@bot lunch
Botユーザーにメンションを付けて「lunch」と発言すると、恵比寿のランキングからランダムに3件のお店を提案してくれます。
3点仕様
コードを読みはすれど碌に書いた事が無く、記事のネタにするには時間も少なかったので仕様は小さくしました。
- Slackでお手軽に使える
- 弊社はSlackBotが多いので、同じような使用感だと良い
- まとめサイトからデータを取得する
- 未知のお店を知りたいので、Rettyからスクレイピングする
- サイトに負荷を掛けたくないので、データをDBに保存するようにアップデート予定
- サーバーにお金を掛けない
- GASは権限の問題で断念
- 勉強目的でもあるので、自分でHerokuに立てる
動作環境
- MacBook Pro (Mojave 10.14.1)
- Ruby 2.5.1
- Heroku
- Slack
各コードの働き
とても簡単なコードですが、処理の流れを追って説明します。
slack-ruby-bot
とmechanize
をミニマムに利用しているので、行数は抑えられているような気がします。
ページ情報の取得
mechanize
のget
メソッドで指定ページの情報を丸ごと取得します。
Rettyは検索フォームから絞り込むと、動的に表示している為かデータが取得できません。
「恵比寿の美味しいランチ20選」のように、データセットが固定されているページを指定します。
query = 'https://retty.me/area/PRE13/PUR1/city/131131500013/'
agent = Mechanize.new
page = agent.get(query)
データの選別
続けてmechanize
の.search
メソッドでページから指定したクラスの要素だけ抜き出します。
店名とリンクが欲しかったので<a>
タグにしています。
Rettyは店舗情報なども取れてしまうので、改行で分けるという荒技で対応しました。
restaurants = {}
elements = page.search('a.restaurant__block-link')
elements.each do |element|
info = element.inner_text.split("\n")
restaurants.merge!(info[1].strip => element[:href])
end
restaurants = restaurants.to_a.sample(3)
Slackへの送信
あとは適当に発言内容を整形して、slack-ruby-bot
のsay
メソッドでSlackに送ります。
client.say(text: recommend_comment, channel: data.channel)
お使いになるには
STEP 1: SlackAPIを作る
- 公式サイトの「Start Building」ボタンをクリックしてAPIを作成します
- [Bot User]ページでBotを作成します
- [OAuth & Permissions]ページの「Scopes」でBotがメッセージを送信できる権限を許可します
- 同じページの「Install App to Workspace」ボタンをクリックしてBotの利用を許可します
- アプリの認証に必要な「Bot User OAth Access Token」を控えておきましょう
STEP 2: Herokuで起動する
- Herokuで新しくAppを作成します
- Herokuにアプリをアップロードしてデプロイします
- CLIでもGitHub連携でもお好みの方法でどうぞ
- GitHubのアカウントがあれば、Forkして連携すると楽だと思います
- SlackのTokenを環境変数に保存します
- 変数名は「SLACK_API_TOKEN」としてください
参考リンク
おわりに
今回は力量を超えた初挑戦を盛り込み過ぎて、これだけ小さくしても50時間くらい掛かりました。
改善の余地しかないので、これからも更新し続けていきたいと思います。
ゆくゆくは早くも先輩方から「機械学習でベストなランチを提案すると良いよね」「AWSも使えると良いね」と下知された機能まで搭載できると良いなと夢見ています。