WorkatoでRubyを利用する

  • 投稿日:
  • by
  • カテゴリ:

Author

大野 智之Tomoyuki Ohno

大野 智之

Workato(ワーカート)には、Slackとの親和性が抜群のWorkbotという機能があります。
このWorkbotとRubyコネクタを組み合わせて、Slackから「地域のオススメなランチ情報」を入手するボットを作ってみたいと思います。

Workatoは対象ソフトウェアで接続するコネクタと設定し、トリガー(条件)とアクション(実行)を設定するだけで業務を自動化できる優れたツールですが、これだけでは実現できないプロセスや処理があった場合は『Rubyコネクタ』を使うと便利です。
Rubyコネクタを利用するにはRuby言語を理解する必要はありますが、これにより複雑な処理に対応することができます。

今回は、Rubyコネクタを利用してHTMLスクレイピングを行ってみました。

Rubyコネクタとは

Rubyコネクタは、前述の通りWorkato上でRubyのコードを実行するためのコネクタです。コードの実行は、外部のサービス(アプリケーション)を利用することなく、Workato内で処理が完結します。

ただし、利用可能なメソッド・プロパティは制限があり、Rubyに標準で用意されたメソッド・プロパティと、下記URLに記載のメソッド・プロパティに限られます。また、外部ライブラリは利用出来ません。

https://docs.workato.com/developing-connectors/sdk/methods.html

また、標準のメソッドであっても、レシーバーを直接書き換えるものは利用できません。(例えば、hoge.gsub!やhoge.pushなど)
色々と制限はありますが、応用の幅が広いコネクタですので、覚えておいて損はありません。

WorkatoだけでWebサイトのスクレイピングを行ってみる

WorkatoはAPIを備える様々なアプリケーション同士を組み合わせることで、様々なオートメーションを実現することが出来ますが、外部サービスの中にはAPIが提供されていないものも存在します。

このようなサービスからデータを取得してWorkatoで処理する方法の1つとして、Webスクレイピングを行う方法が挙げられます。

WorkatoでWebスクレイピングを行う方法には、Parsehub(https://www.parsehub.com/)があります。ParsehubコネクタもWorkatoに標準で用意されていますので、通常はこれを利用するのがベターでしょう。

しかし、今回は敢えてRubyコネクタでWebスクレイピングにチャレンジしてみます。

WorkatoのRubyコネクタでWebスクレイピング際の注意点

RubyでWebスクレイピングを行う場合、Nokogiriがよく利用されます。しかし、WorkatoのRubyコネクタでは、Nokogiriを含めて外部ライブラリを利用することができません。

このため、標準メソッド・プロパティおよびWorkatoが対応するメソッド・プロパティの範囲でコーディングを行う必要があります。

実装例

Rubyコネクタを利用したWebスクレイピングを行う際のレシピは、次のとおりとなります。

このレシピでは、リックソフト本社の近くにある、東京サンケイビルの敷地内で平日昼間に展開される「ネオ屋台村」のランチスケジュールを取得して、Slackの特定のチャンネルへ投稿します。

ただし、上記ランチスケジュールにはAPIやRSSなどの構造化されたデータを取得する手段が存在しないため、Webスクレイピングで必要な値を取得していきます。

実装例

上記レシピの各タスクでは、以下のような処理が実装されています。

Trigger SlackのWorkbotに対して、「otemachi lunch sankei」というメッセージ(コマンド)を送信すると、実行結果がSlack上に返されます。
Actions SlackのWorkbotに対して、「otemachi lunch sankei」というメッセージ(コマンド)を送信すると、実行結果がSlack上に返されます。
「ネオ屋台村」のランチスケジュールのHTMLを取得します。
Rubyコードを実行します。
ループ用の変数を初期化します。(Rubyの実行結果より出力された配列の値を、For eachループで0,1,2,3・・・といった形で順番に取得するため)
Rubyの実行結果をFor eachループします。
Rubyの実行結果より1件取得(指定された配列のインデックスより取得)し、Slackにその結果を返します。
ループ用の変数をインクリメント(+1)します。

このうち、Rubyのコードは次のようになっています。

前述の通りNokogiri等の外部ライブラリが利用できないため、特定の文字列が出現したら処理を行うという実装となります。

[html] # @param input [Hash] input hash supplied in the recipe step # @return value returned in the last line # Eg: Code for returning country code for an IP address # { # country_code: get("http://freegeoip.net/json/" + input["ip_address"]) # } output = "" flg = false s = input['html_body'] res = [] flg_a = false flg_b = false flg_c = false shop_name = "" car_img_url = "" food_img_url = "" description = "" cnt = 0 s.split("\n").each do | line | tmp = line.strip # Check Today's shops block. if tmp.include?('<li class="active"><!-- date -->') then flg_a = true next end if tmp.include?("</li><!-- date -->") then flg_a = false end if flg_a == false then next end # Fetch Today's shops. if tmp == "<li><!-- cnt_archive_lists_col02 li -->" then shop_name = "" car_img_url = "" food_img_url ="" description = "" flg_b = true next end if tmp.include?("cnt_modalbox") then flg_b = false end if flg_b == false next end # Exclude a tag if tmp.include?("<a ") || tmp.include?("</a>") then next end # Get shop name if tmp.include?("<h4") then shop_name = tmp.gsub('<h4 class="cnt_archive_lists_ttl"><span class="link_icon link_icon_arrow">','') shop_name = shop_name.gsub('</span></h4>','') shop_name = shop_name.strip end # Get car_photo_img_url if tmp.include?("cnt_archive_lists_img") then car_img_url = tmp.gsub('<span class="cnt_archive_lists_img resize_img"><img src="','') car_img_url = car_img_url.gsub('" alt=""></span>','') car_img_url = car_img_url.strip end # Get food_photo_img_url if tmp.include?("cnt_archive_lists_thumb") then food_img_url = tmp.gsub('<span class="cnt_archive_lists_thumb resize_img"><img src="','') food_img_url = food_img_url.gsub('" alt=""></span>','') food_img_url = food_img_url.strip end # Get description if tmp.include?("cnt_archive_lists_txt") then flg_c = true next end if flg_c == true description = tmp.gsub('<p>','') description = description.gsub('</p>','') description = description.gsub('</div>','') description = description.strip flg_c = false res[cnt] = { "shop_name" => shop_name, "car_img_url" => car_img_url, "food_img_url" => food_img_url, "description" => description } cnt = cnt + 1 next end end { result: res } [/html]

レシピを実行してみる

SlackのWorkbotで「otemachi lunch sankei」と入力すると、レシピが実行されます。
実行されると、以下のように当日のランチがSlackに投稿されます。

コンテンツと会話をつなぐ

動画

おわりに

今回は、WorkatoのRubyコネクタの利用例としてWebスクレイピングを行ってみました。
このような使い方が適切かどうかはありますが、Rubyコネクタとは何か、どのように利用できるのかがお分かりいただけると思います。
また、iPaaS製品の中でもWorkatoは柔軟性が高く、かつ簡単に使える製品であることもご理解いただけると思います。
iPaaS製品の導入を検討の際は、Workatoを是非ご検討ください。

お問い合わせ

製品についてはこちらをご覧ください。

Workato