LoginSignup
6
5

More than 5 years have passed since last update.

enebularとimport.ioでPlayStation VRの価格をAWS Lambdaで監視してSlackで通知

Last updated at Posted at 2016-12-17

概要

import.ioを利用して購入を検討している価格.comのPlayStation VR CUHJ-16000のランキング情報を1時間おきに取得して希望金額を下回った店舗だけをSlack通知します。

import.ioの設定

import.ioのダッシュボード左上にある"New Extractor"をクリックします。

image

以下の"Insert a URL with data here"にPlayStation VR CUHJ-16000のURL( http://kakaku.com/item/K0000835986/ )を入力して"Go"をクリックします(もちろん、お好みの商品ページで問題ありません)

image

以下のように良い具合にランキングの部分をデータ化してくれました。

image

以下のようにすると列が削除できますので必要な列だけにします。今回は店名と価格だけします。

image

列を絞ったら最後に"Done"をクリックします。

image

Flowの作成

import.ioで作成したAPIのURLは以下の"Integrate"で確認できます。今回使うURLは"Live query API"です。

image

それでは、enebular Flowを作成します。まずは以下のようにInjectノードとHTTP RequestノードとDebugノードをつなげます。

image

HTTP RequestノードのURLに先ほどのimport.ioの"Live query API"を入力します。

image

これで実行するとDebugに以下のような文字列が表示されます。

{
    "extractorData": {
        "url": "http://kakaku.com/item/K0000835986/",
        "resourceId": "8398f7d35a6a30eb23a8e7f5d7e8a005",
        "data": [{
            "group": [{
                "Fontprice price": [{
                    "text": "¥64,797"
                }],
                "Wordwrapshop link": [{
                    "text": "KADEN SHOP",
                    "href": "http://kakaku.com/shop/2184/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥64,798"
                }],
                "Wordwrapshop link": [{
                    "text": "DC-LIFE",
                    "href": "http://kakaku.com/shop/2134/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥64,799"
                }],
                "Wordwrapshop link": [{
                    "text": "S-SALE",
                    "href": "http://kakaku.com/shop/2119/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥65,800"
                }],
                "Wordwrapshop link": [{
                    "text": "ケレス.com",
                    "href": "http://kakaku.com/shop/2390/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥67,000"
                }],
                "Wordwrapshop link": [{
                    "text": "オールワン電気",
                    "href": "http://kakaku.com/shop/2059/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥68,686"
                }],
                "Wordwrapshop link": [{
                    "text": "アウトレットプラザ",
                    "href": "http://kakaku.com/shop/610/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥69,032"
                }],
                "Wordwrapshop link": [{
                    "text": "エクセラー",
                    "href": "http://kakaku.com/shop/2350/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥69,800"
                }],
                "Wordwrapshop link": [{
                    "text": "エクセラー",
                    "href": "http://kakaku.com/shop/1455/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥71,159"
                }],
                "Wordwrapshop link": [{
                    "text": "Premium Outlet Plaza",
                    "href": "http://kakaku.com/shop/2482/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }, {
                "Fontprice price": [{
                    "text": "¥81,000"
                }],
                "Wordwrapshop link": [{
                    "text": "QQstore.jp",
                    "href": "http://kakaku.com/shop/2243/?pdid=K0000835986&lid=shop_itemview_shopname"
                }]
            }]
        }]
    },
    "pageData": {
        "resourceId": "8398f7d35a6a30eb23a8e7f5d7e8a005",
        "statusCode": 200,
        "timestamp": 1481801622181
    },
    "url": "http://kakaku.com/item/K0000835986/",
    "runtimeConfigId": "0036e3e0-377e-4049-833c-29a70471264b",
    "timestamp": 1481802205829,
    "sequenceNumber": -1
}

Fontprice priceとかWordwrapshop linkとかスペースが含まれていると取り扱い難いのでスペースを_(アンダースコア)に変換します。以下のようにChangeノードを追加します。

image

Changeノードは以下のようなChange設定にすることで再帰的にスペースをすべて_(アンダースコア)に置換します。

image

あと、気をつけなければいけないのはJSONオブジェクトではなく文字列なのでJSONノードを置いてJSONオブジェクトへ変換します。

image

次にランキングの各店舗の金額で希望金額を下回ったものだけを抽出する以下のようなコードをFunctionノードに書きます(希望金額がハードコーディングされてますが本来はもっと工夫すべきですね)

var shop, price, data = msg.payload.extractorData.data[0].group;
msg.notif = false; // 希望金額を下回る店舗の有無フラグ
msg.payload = '';

for (i = 0; i < data.length; i++) {

    shop = data[i].Wordwrapshop_link[0].text;
    price = data[i].Fontprice_price[0].text.replace('¥', '').replace(',', '');

    // 希望金額と比較(本来はハードコーディングでない方法にしましょう)
    if (price < 64400) {

        // 希望金額を下回る店舗が1店舗でもあればtrueにする
        msg.notif = true; 

        // 希望金額を下回った店舗の店名と金額とリンクをpayloadに追加
        // Slackで通知するために解りやすい体裁のテキストにしている
        msg.payload += shop + ': ' + data[i].Fontprice_price[0].text + '円 <' + data[i].Wordwrapshop_link[0].href + '>\n'; 
    }
}
return msg;

その次にSwitchノードを置いてmsg.notiftrueの場合のみ後続へ続くように設定します。

image

image

Slack通知

Slackの"Apps & integrations"をクリックします。

スクリーンショット 2016-12-16 20.25.57.png

"Find a new app, or a service you already use"に"webhook"と入れてサジェストされる"Incoming WebHooks"を選択します。

image

続いて"Add Configuration"をクリックします。

image

通知したいチャネルを選択して"Add Incoming WebHooks integration"をクリックします。

image

これで設定完了です。次の画面の"Example"の通りcurlなどで動作確認しましょう。

image

enebular Flowに戻って以下のようにSlackノードを置きます。

image

Slackノードの設定は以下のような感じです。

image

これで一度Flowを実行して以下のようにSlackに通知されればOKです(動作確認なので必ず通知されるように下回る希望金額を設定しましょう)

image

Export to Other ServicesでAWS Lambdaにデプロイ

enebularのFlowエディタは開発用途で一時的に利用するものなので作成したロジックを安定した環境で動かすためにExport to Other ServicesでAWS Lambdaにデプロイします。AWS Lambdaで動かすためにはAWS LambdaのInput/Outputで起動するようにaws lambda request/responseノードをFlowに追加します。

[{"id":"6901f707.bd2f2","type":"inject","z":"c4d430a6.5496f","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":117,"y":29,"wires":[["b55bf317.aaaf1"]]},{"id":"b55bf317.aaaf1","type":"http request","z":"c4d430a6.5496f","name":"","method":"GET","ret":"txt","url":"<import.ioのLive query API URL>","x":311,"y":54.5,"wires":[["c11dc614.37d168"]]},{"id":"d2ae2484.3e5918","type":"json","z":"c4d430a6.5496f","name":"","x":125.5,"y":119.75,"wires":[["4b3ebd57.942b54"]]},{"id":"3cb45b47.7ce6f4","type":"debug","z":"c4d430a6.5496f","name":"","active":true,"console":"false","complete":"payload","x":566,"y":168,"wires":[]},{"id":"c11dc614.37d168","type":"change","z":"c4d430a6.5496f","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":" ","fromt":"str","to":"_","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":507,"y":56,"wires":[["d2ae2484.3e5918"]]},{"id":"7b4236e2.df01","type":"aws-lambda-request","z":"c4d430a6.5496f","x":109.5,"y":73.5,"wires":[["b55bf317.aaaf1"]]},{"id":"14e89f5f.296731","type":"aws-lambda-response","z":"c4d430a6.5496f","x":345.5,"y":181,"wires":[]},{"id":"4b3ebd57.942b54","type":"function","z":"c4d430a6.5496f","name":"","func":"var shop, price, data = msg.payload.extractorData.data[0].group;\nmsg.notif = false;\nmsg.payload = '';\nfor (i = 0; i < data.length; i++) {\n    shop = data[i].Wordwrapshop_link[0].text;\n    price = data[i].Fontprice_price[0].text.replace('¥', '').replace(',', '');\n    if (price < 64400) {\n        msg.notif = true;\n        msg.payload += shop + ': ' + data[i].Fontprice_price[0].text + '円 <' + data[i].Wordwrapshop_link[0].href + '>\\n'; \n    }\n}\nreturn msg;","outputs":1,"noerr":0,"x":253.5,"y":120.5,"wires":[["dcf58bbb.bd5498"]]},{"id":"dcf58bbb.bd5498","type":"switch","z":"c4d430a6.5496f","name":"","property":"notif","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","outputs":1,"x":376.5,"y":121.5,"wires":[["264fe0f3.637cb8","3cb45b47.7ce6f4","6c12cbb3.8293ac"]]},{"id":"264fe0f3.637cb8","type":"slack","z":"c4d430a6.5496f","name":"","channelURL":"<Slackで作成したWebHook URL>","username":"webhookbot","emojiIcon":"","channel":"","x":543.5,"y":119,"wires":[]},{"id":"6c12cbb3.8293ac","type":"delay","z":"c4d430a6.5496f","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":145.5,"y":182.5,"wires":[["14e89f5f.296731"]]}]

ここで注意なのがAWS Lambda Responseノードの前にあるDelayノードです。Slack通知の処理が完了する前にAWS Lambda Responseノードが動いてしまうとLambda functionが終了してしまいますのでデフォルトの5秒待つようにしています。

image

次に以下のようにしてAWS Lambdaデプロイ画面を開きます。

image

functionの属性を入力してデプロイします。この辺りの詳細はenebular Depelopersを参照ください。

image

最後にAWS Lambdaのトリガを設定します。

image

開いたダイアログの赤枠の部分をクリックしていって"CloudWatch Events - Schedule"を選択します。

image

スケジュールを設定する画面になりますので、任意のルール名とdescriptionを入力します。監視間隔は価格.comさんに迷惑がかからないように1時間間隔にします。

image

これで自動化OKです!

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5