Developer's Blog

Nightmare ことはじめ

こんにちは。
ウェブ共同開発部 島根支社の林です。

皆さんは PhantomJS というライブラリをご存知でしょうか。
PhantomJS は Web ページの操作の自動化を行うことができる優れたライブラリです。
しかし、ページの操作のために page.evaluate を使おうとすると、コールバック関数でコールバック関数を呼び、といった感じでネストが深くなってしまいがちです。
そこで今回皆さんに紹介したいのが Nightmare です。

Nightmare とは

Nightmare とは PhantomJS と同様に Web ページの操作を自動化するための Node.js によるライブラリです。
Nightmare 公式ページ

Nightmare は PhantomJS と違い Promise ベースで実装されているため、処理を簡潔に記述することができます。
そして何より、大量のコールバック関数から解放されます。

今回は

  • Developer’s Blog にアクセス
  • 最新の記事のタイトルをクリック
  • 記事の URL を表示

という処理を例に、Nightmare について説明します。

パッケージのインストール

まずは Nightmare をインストールしましょう。
npm 経由でインストールすることができます。

 $ npm install --save nightmare 

サンプル

こちらが今回のサンプルになります。

const Nightmare = require('nightmare');
const nightmare = Nightmare({ show: true });

nightmare
 .goto('https://blog.fenrir-inc.com/jp/')
 .click('.section:first-child .entry-title a')
 .url()
 .end()
 .then((url) => console.log(url));

簡単ですね。

最初に行っているのは Nightmare のロード・インスタンス生成です。

const Nightmare = require('nightmare');
const nightmare = Nightmare({ show: true });

インスタンス生成の際、引数にオプションを追加することで Nightmare の動作を制御することができます。
今回は { show: true } というオプションを指定していますが、こちらはウィンドウを表示するオプションです。
Nightmare が動作している様子をわかりやすく把握することができます。

そして以下の部分が今回行う3つの処理の実働部となります。

nightmare
 .goto('https://blog.fenrir-inc.com/jp/')
 .click('.section:first-child .entry-title a')
 .url()
 .end()
 .then((url) => console.log(url));

goto(url) は url で指定されたページをロードします。
click(selector) は CSS のセレクタ書式で選択されたエレメントをクリックします。
url() は現在のページの url を返します。
end() で Nightmare で行われているプロセスをすべて終了します。
最後に then(callback) で今回取得した URL を確認するため、コンソールに出力しています。

このように Nightmare の API はメソッドチェーンで書けるので、処理の流れを直感的に記述することができます。
非常に分かりやすいですね。

他にも指定時間、あるいは特定のセレクタにマッチするエレメントが出現するまで処理を遅延させる wait() 、フォーム部品を操作する check()select() など分かりやすいメソッドが充実しています。
これも Nightmare の魅力のひとつです。

最後に

今回は Nightmare について説明をさせていただきました。
私自身 Nightmare の機能を把握しきれていない部分が多く、触り程度の説明になってしまいましたが、いかがでしたでしょうか。
皆さんも是非 Nightmare を使ってみてください。

 

フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!

Copyright © 2019 Fenrir Inc. All rights reserved.