LoginSignup
9
1

More than 3 years have passed since last update.

enebular内のフローに自動でアクセスしてトリガーを引く

Last updated at Posted at 2019-12-01

enebular Advent Calendar 2019の2日目を担当します、ニアムギです。
今回はhttp://enebular.com/app に自動でアクセスしてフローのトリガーを引く方法を紹介したいと思います。

やり方

スクレイピングします。

きっかけ

enebularで作成したNode-REDのフローは、最終的に何かしらのデバイスやサービスにデプロイします。
ただせっかくenebular上にフローがあるのに、それを使わないのはもったいないなと…
そこで、自動でフローを開いて実行出来たら活用できるのでは?と思い、試してみました。

試してみる

テスト用のNode-REDフローを書く

injectノード"start"のボタンをクリックするとhttpリクエストでGCPのCloudFunctionsを実行するだけのフローです。
enebular_node_red.PNG

※フローは何でも良いので、自分なりに確認しやすいフローにしました。
※詳しく知りたい方はNode-RED+CloudFunctionsでPythonを動かすを参照下さい。

http://enebular.com/app をスクレイピングする

Webページを開くところから手順を踏みながら調べていきます。
プログラムはスクレイピングのしやすいpythonで書いています。

ログインする


http://enebular.com/app を開いて、メールアドレスが入力できるまで待ちます。

WebDriverWait(driver, 5).until(ec.element_to_be_clickable((By.NAME, "email")))

開いたらメールアドレスとパスワードを入力してEnterキーを押します。

id = driver.find_element_by_name("email")
id.send_keys(un)
password = driver.find_element_by_name("password")
password.send_keys(pw)
password.send_keys(Keys.ENTER)

アセットを選択する


選択するアセットが表示されるまで待ちます。今回は"testscraping"です。

assetNm = "testscraping"
assetPath = '//span[@data-testid="' + assetNm +'"]'
WebDriverWait(driver, 5).until(ec.element_to_be_clickable((By.XPATH, assetPath)))

表示されたらアセットをクリックします。

driver.find_element_by_xpath(assetPath).click()

Overviewにある"edit"ボタンを押す


アセットのOverviewが表示されるまで待ちます。
右側にあるEditボタンをクリックできる時が表示された時と判断します。

editBtn = '//button[@data-testid="btn-edit-flow"]'
WebDriverWait(driver, 5).until(ec.element_to_be_clickable((By.XPATH, editBtn)))

表示されたらEditボタンをクリックします。

driver.find_element_by_xpath(editBtn).click()

タブを切り替える

Editボタンをクリックすると別タブにフローが表示されます。そのためタブを切り替える必要があります。

handle_array = driver.window_handles
driver.switch_to.window(handle_array[1])

フローが表示されるのを待つ

ここが一番の難関です。

まず"Loading..."が表示されます。


次にフローを編集するフレームなどが表示されます。 この時はまだフローのタブが表示されていません。


しばらく経ってからフローのタブ(今回はdummyとinput)が表示されます。

フレームの表示とタブの表示タイミングが異なるため工夫が必要です。
フローが正しく表示される(=タブが表示される)までフレームの読み込みを繰り返すことで解決しました。("while True"で待つのはよろしくないですね…時間制限を持たせるべきですね…)

flowNm = 'input'
frame = '//div[@id="iframeBlock"]/iframe'
flowPath = '//a[@title="' + flowNm + '"]'

# Loading... が終わるのを待つ
WebDriverWait(driver, 30).until(ec.frame_to_be_available_and_switch_to_it((By.XPATH, frame)))

# フローが完全に表示されるまで待つ
while True:
    # フレームを元に戻す
    driver.switch_to.default_content()
    # フレームを切り替える
    iframe = driver.find_element_by_xpath(frame)
    driver.switch_to_frame(iframe)        

    try:
        # フローが正しく表示されていない場合はExceptionになる
        WebDriverWait(driver, 1).until(ec.visibility_of_element_located((By.XPATH, flowPath)))
        break
    except:
        pass

表示されたらタブをクリックします。

driver.find_element_by_xpath(flowPath).click()

トリガーを押す


今回はinjectノード"start"のボタンをクリックさせてフローを実行させます。
ノードにたどり着くまでがなかなか面倒です。

triggerNodeNm = 'start'
try:
    # canvasまで移動
    workspace = driver.find_element_by_id('workspace')
    chart = workspace.find_element_by_id('chart')
    canvas = chart.find_element_by_class_name('innerCanvas')

    # class = "node nodegroup"を探す
    nodes = canvas.find_elements_by_css_selector('.node.nodegroup')
    # ノード名が指定したものと一致しているかチェックする
    # 一致している場合、トリガーを押す
    for node in nodes:
        nodeNm = node.find_element_by_tag_name('text').text
        if nodeNm == triggerNodeNm:
            node.find_element_by_class_name('node_button_button').click()
            break

except Exception as e:
    driver.quit()

トリガーを押せたのであとは画面を閉じて終了です。

driver.quit()

試した結果

プログラムを実行すると・・・

CloudFunctionsの関数が実行されました!

まとめ

スクレイピングすることでenebularのフローを活用できました。
デプロイ先のシステムやインターフェースに依存しないフローであれば、この方法でも良いかもしれません。
(Webページのタグやクラス名などが変わると動かなくなる問題はあります…)

何かのヒントになれば幸いです。ではでは。

9
1
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
9
1