node.jsでスクレイピングしてみた
node.jsの記事を最近チラホラ見かけるので、入門してみました。
node.jsはサーバー書いてこそって感じなんだろうと思いますが、ネットワークプログラミングの経験がないので、まずは他の言語で簡単にできることをnode.jsで書いてみようという趣旨です。
node.jsのインストールとか
node.jsのパッケージマネージャである、npmを使いたかったので、GitHubのnpmのページの方法でインストールしました。
MacPortsにnode.jsはあったんですけど、npmはないし、Homebrewにはnode.jsもnpmもあったんですけど、インストールしたらnpmがうまく動かなかったので、なんだか面倒な方法でインストールすることになった気がしてます。
作ったツール
コマンドラインで以下のように打ち込むと、任意のディレクトリにYahoo!画像検索APIで取得できる画像を保存するサンプルを書きました。*1
node imggetter.js ./MyOppai おっぱい
第一引数でディレクトリ名を指定し、第二引数でキーワードを指定します。
サンプルコード(imggetter.js)
var sys = require('sys'), spawn = require('child_process').spawn, fs = require('fs'), path = require('path'), url = require('url'), querystring = require('querystring'), Apricot = require('apricot').Apricot, async = require('asyncjs'), map = function(arr, func) { return Array.prototype.map.call(arr, func) } if (process.argv.length < 4) return console.log('引数が足りん') var argv_path = /\/$/.test(process.argv[2]) ? process.argv[2] : process.argv[2] + '/', keyword = process.argv[3], target = 'http://search.yahooapis.jp/ImageSearchService/V1/imageSearch', params = { appid: 'YOUR_APP_ID', query: keyword, results: 50, start: 1, adult_ok: 1 } path.exists(argv_path, function(exists) { if (!exists) fs.mkdirSync(argv_path, 0777) }) async.range(1, 951, params.results) .each(function(start, next) { params.start = start Apricot.open([target, querystring.stringify(params)].join('?'), function(xml) { if (!xml.toDOM.getElementsByTagName('ClickUrl')[0]) return async.list(map(xml.toDOM.getElementsByTagName('ClickUrl'), function(el) { return el.firstChild.nodeValue })) .each(function(img_url, next) { var extention = '.' + url.parse(img_url).pathname.match(/\.(.*)?$/)[1], timestamp = (new Date()).toISOString().replace(/:/g, '_').replace('Z', '+09_00'), curl = spawn('curl', ['-o', argv_path + timestamp + extention, img_url]) curl.stderr.on('data', function(data) { sys.print(data) }) curl.stdin.end() next() }) .delay(1000) .end() next() }, true) }) .delay(50000) .end()
delayの時間は、プロセスを立ち上げ過ぎて、終了しない程度に適当な数値を入れてあります。
curlを使っているのが反則な気もしますが、標準モジュールで上手くできなかったので、諦めました。
使ってみた感想など
npmというパッケージマネージャがあるし、JavaScriptで操作できなかったIO周りが操作できるようになったことで、node.jsという名のJavaScriptに酷似した言語を手にいれたような感覚を覚えました。
パッケージも充実してくると、作りたいものをJavaScriptで書くことがより簡単になりそうです。
サーバーも書けるということで、これから勉強したいなと思っているところですが、Rhino版node.jsとかが出て、GoogleAppEngine上で利用できるようになったりするとうれしいなーと思います。
それっぽいのはあるらしいです。GoogleAppEngineで使えるRhino版のサーバーサイドJSがあると教えてもらいました。一見node.jsっぽい感じ。
@taiju #appengine で使える Rhino版 node.js みたいなものは既にありますよー。 URL
2010-10-14 12:36:16 via HootSuite to @taiju
情報も少ないし、まだまだ自分には敷居が高そうです。。。
その他
ちゃんとしたプログラムが未だに書けないので、頑張りましょうワタクシ。
*1:[http://d.hatena.ne.jp/jdg/20080504/1209924643:title=昔も同じようなもの作ってました]けど、あまり成長してないですね