初めてのNode.js学習メモ
先日、Webクローラーと機械学習という言葉に惹かれて、「JS+Node.jsによるWebクローラー/ネットエージェント開発テクニック」という書籍を購入しました。
Node.jsやWebクローラー開発に触れたことがありませんでしたが、書籍を読みつつ、手を動かしてみることで、簡単なWebクローラー作成ができるようになったと思います。ここでは、個人的な学習のまとめを書いてみたいと思います。
なお、機械学習については、まだ理解が追いついていませんのでここでは記述しません。
JS+Node.jsによるWebクローラー/ネットエージェント開発テクニック
- 作者: クジラ飛行机
- 出版社/メーカー: ソシム
- 発売日: 2015/08/31
- メディア: 単行本
- この商品を含むブログ (2件) を見る
前提
- Java,JavaScript,HTMLを使ったWebアプリケーションの開発技術については学習経験があります。
- Node.jsは未経験。
- Windows環境を使用。
- Node.js バージョン4.2.6 を使用。
Node.jsとは
JavaScriptエンジンの一つで、コマンドラインから利用できる。最も普及しているJavaScriptエンジンは、各種ブラウザであるが、セキュリティ面の考慮から、いろいろ制限が多い。Node.jsでは、ファイル処理やネットワーク処理などもできる。さらに、パッケージマネージャー「npm」があり、便利な機能を拡張することが容易。
Node.jsインストール方法
公式サイトから、MSIファイルをダウンロードして、インストール。
※EXEファイル形式もあったけど、npmが入っていなかった。
インストールが終わると、スタートメニューに「Node.js command prompt」が登録されている。これを起動して、次のコマンドを実行できればOK。Windows標準のコマンドプロンプトからも実行できた。
node -v
パッケージマネージャー npm
npmは、Node.jsで、モジュール(拡張機能)をインストールしたりするためのパッケージマネージャー。インストールしたモジュールの管理場所は、グローバルとローカルの2種類がある。
次のようにコマンドラインから使用できる。
npm -v
主な使い方。
npm -h | ヘルプを表示。 |
npm install モジュール名 | モジュールをインストールする。※1 |
npm uninstall モジュール名 | モジュールをアンインストールする。※1 |
npm list | インストールされているモジュールの一覧を表示する。※1 |
npm root -g | グローバル環境のパスを表示する。ホームディレクトリ\AppData\Roaming\npm\node_modules となるようです。 |
※1 上記コマンドでは、ローカル環境を対象とする。ローカル環境とはカレントディレクトリのこと。グローバル環境を対象とする場合は、「-g」オプションをつける。
私が試した時には、グローバル環境にインストールしたモジュールを使おうとして、「Cannot find module XXX」とエラー表示されることがありました。その場合、次のように環境変数を設定すると、解決しました。
set NODE_PATH=グローバル環境のパス(npm root -gの結果)
簡単なサンプル
ハローワールドを出力させる。
ワンライナーで実行。
node -e "console.log('Hello World');"
スクリプトを作成して実行する。
helloworld.jsファイル
console.log("Hello World");
node helloworld.js
Node.jsのリファレンス
Node.js v4.3.1 Manual & Documentation
Webページダウンロード(cheerio-httpcliモジュール)
静的なページや、RSS, XMLダウンロードなどに使用可能。逆に、jQuery,Ajaxを多用したようなページでは使用困難な模様。jQuery風に要素を指定できるのが便利。
モジュールインストール
npm install -g cheerio-httpcli
私がインストールしたバージョン
cheerio-httpcli 0.6.4
簡単なスクリプト
Googleで「node.js」を検索して、ページタイトルを標準出力する。
cheerio-httpcli-01.jsファイル var client = require('cheerio-httpcli'); client.fetch('http://www.google.com/search', { q: 'node.js' }, function (err, $, res) { console.log($('title').text()); });
実行
node cheerio-httpcli-01.js
参考ページ
cheerio-httpcli
Node.jsのスクレイピングモジュール「cheerio-httpcli」が第3形態に進化したようです - Qiita
Node.jsのスクレイピングモジュール「cheerio-httpcli」が大規模アップデートして帰ってきた - Qiita
Webページダウンロード(PhantomJS,CasperJSモジュール)
PhantomJSが画面表示しないWebブラウザのようなもの、CasperJSがPhantomJSを簡単に使うためのもの、らしい。
cheerio-httpcliでは操作できなかったWebページでも操作できた。コマンドラインから、casperjsコマンドでJavaScriptを実行することになるが、JavaScript内で使うことができるモジュールには制限がある模様。
Pythonのインストールが必要だった。
モジュールインストール
npm install -g phantomjs npm install -g casperjs
私がインストールしたバージョン
PhantomJS 2.1.1
CasperJS 1.1.0-beta5
簡単なスクリプト
Googleで「node.js」を検索して、ページタイトルを標準出力する。
casperjs-01.jsファイル var casper = require("casper").create(); casper.start("http://www.google.com/search?q=node.js", function(){ this.echo("Title: " + this.getTitle()); }); casper.run();
実行
casperjs casperjs-01.js
参考
CasperJS documentation — CasperJS 1.1.0-DEV documentation
メール送信
Yahoo!JAPANメールを使って、メール送信してみる。
モジュールインストール
Yahoo!JAPANメールを使う場合、SMTPサーバを指定してメール送信する。SMTPサーバを使う場合、nodemailer-smtp-transportをインストールしないとダメだった。nodemailerのバージョンによるのかもしれない。
npm install -g nodemailer npm install -g nodemailer-smtp-transport
私がインストールしたバージョン
nodemailer 2.1.0
nodemailer-smtp-transport 2.2.0
簡単なスクリプト
nodemailer01.jsファイル // 実行方法 if (process.argv.length <= 2) { console.info("Usage: node nodemailer01 user pass"); process.exit(); } var user = process.argv[2]; var pass = process.argv[3]; // SMTPトランスポート作成 var smtpConfig = { host: "smtp.mail.yahoo.co.jp", port: 465, secure: true, auth: { user: user, pass: pass }, // logger: true, // debug: true }; var nodemailer = require("nodemailer"); var smtpTransport = require("nodemailer-smtp-transport"); var transport = nodemailer.createTransport(smtpTransport(smtpConfig)); // メールアドレス var address = user + "@yahoo.co.jp"; // メール情報の作成 var mailOptions = { from: address, to: address, // from: '"Sender Name" <' + address + '>', // to: '"Receiver Name" <' + address + '>', subject: "テストメール", text: "テストメールです。" }; // メール送信 transport.sendMail(mailOptions, function(error, response){ if (error) { console.log(error); throw error; } else { console.log("Message sent: " + response.message); } transport.close(); });
補助的な機能
実行環境取得
console.log("カレントディレクトリ\n" + process.cwd()); console.log("スクリプトパス(絶対パス)\n" + __filename); console.log("スクリプトディレクトリ\n" + __dirname);
var path = require("path"); console.log("スクリプトディレクトリ\n" + path.dirname(__filename)); console.log("スクリプト名\n" + path.basename(__filename)); console.log("スクリプト名(拡張子なし)\n" + path.basename(__filename, path.extname(__filename))); console.log("スクリプト拡張子\n" + path.extname(__filename));
console.log("実行時引数\n", process.argv); console.log("実行時引数の数\n", process.argv.length); console.log("Node.jsコマンド\n" + process.argv[0]); console.log("スクリプトパス\n" + process.argv[1]);
var homedir = process.env[process.platform == "win32" ? "USERPROFILE" : "HOME"]; console.log("ホームディレクトリ\n" + homedir);
参考
Web Tips Plus: node.js ホームディレクトリのパスを取得
環境に合った改行コード
var os = require("os"); console.log("[" + os.EOL + "]");
メッセージ出力
指定メッセージを出力する。
console.log("Hello world."); console.info("Info log"); console.warn("Warn log"); console.error("Error log"); console.trace("Trace log"); //スタックトレースが出力される。
タイムスタンプを付加してメッセージ出力する。
var infolog = require("util").log; infolog("Hello world.");
出力/非出力を切り替え可能なメッセージ出力。
出力したい場合は、環境変数NODE_DEBUGに、debuglog関数の引数と同じ文字列を指定しておく。カンマで区切って複数指定することも可能。
var debuglog = require("util").debuglog("myapp"); debuglog("デバッグログです。");
set NODE_DEBUG=myapp
正規表現
簡単に正規表現が使える。あ、これはフツーのJavaScriptの機能だ。
console.log("abcde12345".match(/bcd/g)); //-> [ 'bcd' ] console.log("abcde12345".replace(/bcd/g, "BCD")); //=> aBCDe12345
設定ファイル(configモジュール)
モジュールインストール
npm install -g config
簡単なスクリプト
script/nodejs01.jsファイル var config = require("config"); console.log(config.test01);
簡単な設定ファイル
JSON5など、いくつかの形式が使える。
config/default.json5ファイル // default.json5 { "test01": "hello world", }
参考
node.jsのいろいろなモジュール13 – node-configで設定ファイルを切り替えたりする | Developers.IO
ファイル入出力
var fs = require("fs"); fs.writeFileSync("./file-01_out.txt", "ハローワールド", {encoding:"UTF-8"}); var text = fs.readFileSync("./file-01_out.txt", {encoding:"UTF-8"}); console.log(text);
参考
File System Node.js v4.3.1 Manual & Documentation
文字コード
Node.jsでは、内部的にはUTF-16が使用されているらしい。Node.jsは、Shift_JISには対応していないらしいので、Shift_JISを扱うときは、文字コード変換するモジュールが必要。
モジュールインストール
npm install -g iconv-lite
私がインストールしたバージョン
iconv-lite 0.4.13
iconv-liteで対応している日本語文字コードは、UTF-8, CP932, Shift_JIS, EUC-JP。個人的にはこれだけあれば十分だと思う。
var iconv = require("iconv-lite"); var fs = require("fs"); fs.writeFileSync( "./iconv-lite-01_out.txt", iconv.encode("ハローワールド", "Shift_JIS"), "binary"); var text = iconv.decode( new Buffer(fs.readFileSync("./iconv-lite-01_out.txt", "binary"), "binary"), "Shift_JIS"); console.log(text);
参考
GitHub - ashtuchkin/iconv-lite: Convert character encodings in pure javascript.
外部コマンド実行
同期、非同期で実行することが可能。実行する外部コマンドが標準出力などをするときは、文字コードに注意する。
同期的に、dirコマンドを実行してみる。
var childProcess = require("child_process"); var iconv = require("iconv-lite"); var buffer = childProcess.execSync("dir", { timeout: 60 * 1000, // タイムアウト1分 }); console.log(iconv.decode(buffer, "Shift_JIS"));
参考
Child Process Node.js v4.3.1 Manual & Documentation
暗号化・復号化
Node.js標準機能のcryptoで、各種アルゴリズムで、暗号化・復号化ができる。
var crypto = require("crypto"); if (process.argv.length <= 2) { console.log("Usage: node crypto03.js アルゴリズム 暗号化キー 暗号化対象文字列"); console.log("主要なアルゴリズム"); console.log("aes128, aes192, aes256 - https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard"); console.log("des, des3 - https://ja.wikipedia.org/wiki/Data_Encryption_Standard"); console.log("blowfish - https://ja.wikipedia.org/wiki/Blowfish"); console.log("アルゴリズム一覧"); var cipers = crypto.getCiphers(); console.log(cipers); return; } // アルゴリズム var algorithm = process.argv[2]; console.log("アルゴリズム: " + algorithm); // 暗号化キー var key = process.argv[3]; console.log("暗号化キー: " + key); // 暗号化対象文字列 var plainText = process.argv[4]; console.log("暗号化前: " + plainText); // 暗号化 var cipher = crypto.createCipher(algorithm, key); var cryptedText = cipher.update(plainText, "utf8", "hex"); cryptedText += cipher.final("hex"); console.log("暗号化後: " + cryptedText); // 復号化 var decipher = crypto.createDecipher(algorithm, key); var decryptedText = decipher.update(cryptedText, "hex", "utf8"); decryptedText += decipher.final("utf8"); console.log("復号化後: " + decryptedText);
JSONとJavaScriptオブジェクトの相互変換
var obj = { "item1": "value1" }; var jsonText = JSON.stringify(obj); console.log(jsonText); var jsonObj = JSON.parse(jsonText); console.log(jsonObj);
XML/RSS/HTMLの解析
cheerioを使うと、jQuery風に解析出来て楽。
モジュールインストール
npm install -g cheerio
私がインストールしたバージョン
cheerio 0.20.0
簡単なスクリプト
var html = "" + "<html>" + "<body>" + "<h1>タイトル</h1>" + "</body>" + "</html>" ; var cheerio = require("cheerio"); $ = require("cheerio").load(html); console.log($.html()); console.log($("h1").text());
CSVデータの読み書き
comma-separated-valuesというモジュールをインストールすると、CSVデータを簡単に扱えるようになる。
私がインストールしたバージョン
comma-separated-values 3.6.4
簡単なスクリプト
var data = "" + "h1,h2,h3\r\n" + "v11,v12,v13\r\n" + "v21,v22,v23\r\n" + "v31,v32,v33\r\n" ; var CSV = require("comma-separated-values"); // CSVテキストを読み込み、2次元配列を作成する。 var csvArray = new CSV(data).parse(); console.log(csvArray); // ->出力結果 // [ [ 'h1', 'h2', 'h3' ], // [ 'v11', 'v12', 'v13' ], // [ 'v21', 'v22', 'v23' ], // [ 'v31', 'v32', 'v33' ] ] // CSVテキストを読み込み、オブジェクト配列を作成する。 var csvObjs = new CSV(data, {header:true}).parse(); console.log(csvObjs); // ->出力結果 // [ { h1: 'v11', h2: 'v12', h3: 'v13' }, // { h1: 'v21', h2: 'v22', h3: 'v23' }, // { h1: 'v31', h2: 'v32', h3: 'v33' } ] // オブジェクト配列を、CSVテキストに変換する。 var csvText = new CSV(csvObjs).encode(); console.log(csvText); // ->出力結果 // "v11","v12","v13" // "v21","v22","v23" // "v31","v32","v33"
以上で、学習したことを一通り書いてみたはず。