Charlie Robbins「jsdom.jsとjquery使ったスクレピング」
nodejitsu.com 2010.9.24のエントリ
jsdom + jQuery in 5 lines with node.js
- node.jsでスクレイピング
- jsdom使うと取得したhtmlへDOMが使えるようになる
- 慣れ親しんだjqueryのセレクターapi使ってスクレイピング
- request/http-agentモジュール使って標準モジュール(=http)だけで書くよりもコードすっきり
という内容のエントリ
サンプルコード修正しないと動かない
以下斜め読んだ内容
- 他の言語で生じる面倒事がない
- (補足)
- 断言してるがこの記事で紹介されてるjsdomモジュールでも色々直さないといけない問題あり
- Issues - tmpvar/jsdom - GitHub
- (補足)
- jsdomとjsライブラリ(ex.jquery)があるから
//jsdom例:動かない(cmd.exe) //"/path/to/jquery.js"を指定しても動かない var jsdom = require('jsdom').jsdom, sys = require('sys'), window = jsdom().createWindow(); jsdom.jQueryify(window, '/path/to/jquery.js', function (window, jquery) { window.jQuery('body').append("<div class='testing'>Hello World</div>"); sys.puts(window.jQuery(".testing").text()); // outputs Hello World });
//少し書き直したら動いた(cmd.exe,osx) //モジュール読み込み var jsdom = require('jsdom'), sys = require('sys'), //windowオブジェクト(DOM/BOMがつかえる)作成 window = jsdom.jsdom().createWindow();//jsdom().createWindow()にしない。 //windowオブジェクトへjqueryをロード、ロード完了後にコールバック jsdom.jQueryify(window, "./jquery.js", //このファイルを同じディレクトリにある場合はOK。省略可。 function (window,jquery) { //window.〜は省略できない。ブラウザのときと違う。$も何もしないとエラーになる。 var $=window.jQuery;//この1行入れると、$()使ってかける。 $("body").append("<div class='testing'>Hello World</div>"); sys.puts( $(".testing").text() ); // outputs Hello World });
- 上のソース例でやってること
- jsdom windowオブジェクト作って
- script要素作って、script要素からjqueryロードしてる
- node.jsではウェブページの取得が簡単にできる
- 標準のhttpモジュールで各コードはやや冗長
- requestとhttp-agent使うとすっきりかける。
- request/http-agentともにnpm経由でインストールできる
//必要モジュールインストール npm install request http-agent htmlparser jsdom
//request.js使用例 var request = require('request'), sys = require('sys'); request({uri:'http://www.google.com'}, function (error, response, body) { if (!error && response.statusCode == 200) { sys.puts(body) // Print the google web page. } }); //http-agent使用例 var httpAgent = require('http-agent'), sys = require('sys'); var agent = httpAgent.create('www.google.com', ['finance', 'news', 'images']); agent.addListener('next', function (err, agent) { sys.puts('Body of the current page: ' + agent.body); sys.puts('Response we saw for this page: ' + agent.response); // Go to the next page in the sequence agent.next(); }); agent.addListener('stop', function (err, agent) { sys.puts('the agent has stopped'); }); agent.start();
requestとjsdomを組み合わせてスクレイピング //動かない。 //"Your custom logic"を書いても同じ //'path/to/jquery.js'を指定しても同じ var request = require('request'), jsdom = require('jsdom'), sys = require('sys'); request({uri:'http://www.google.com'}, function (error, response, body) { if (!error && response.statusCode == 200) { var window = jsdom.jsdom(body).createWindow(); jsdom.jQueryify(window, 'path/to/jquery.js', function (window, jquery) { // jQuery is now loaded on the jsdom window created from 'body' jQuery('.someClass').each(function () { /* Your custom logic */ }); }); } });
//少し修正したら動いた(cmd.exe, osx) var request = require('request'), jsdom = require('jsdom'), sys = require('sys'); //指定URLをロードし、ロード後にコールバック //コールバックの第3引数bobyにhtmlソースが入ってる request({uri:'http://www.google.com'}, function (error, response, body) { if (!error && response.statusCode == 200) { // var window = jsdom //読み込み済モジュール指定 .jsdom(body)//渡したhtmlソースからDOMツリー構築 .createWindow();//構築したDOMツリーをwindowオブジェクトへappend //jqueryロードし、ロード後(loadイベント発火後)にコールバック //'path/to/jquery.js'は省略可。google cdnからロードされる jsdom.jQueryify(window, function (window) { var $=window.jQuery;//この1行入れると、$()使ってかける。 $('.gb2').each(function () {console.log($(this).text())}); }); } });
jsdom/http-agent組み合わせて複数ページでスクレイピング
//動かない(cmd.exe、 //"Your custom logic"を書いても同じ //'path/to/jquery.js'を指定しても同じ var httpAgent = require('http-agent'), jsdom = require('jsdom'), sys = require('sys'); var agent = httpAgent.create('www.google.com', ['finance', 'news', 'images']); agent.addListener('next', function (agent) { var window = jsdom.jsdom(agent.body).createWindow(); jsdom.jQueryify(window, 'path/to/jquery.js', function (window, jquery) { // jQuery is now loaded on the jsdom window created from 'agent.body' jQuery('.someClass').each(function () { /* Your custom logic */ }); agent.next(); }); }); agent.addListener('stop', function (agent) { sys.puts('the agent has stopped'); }); agent.start();
//書き直したら動いた(cmd.exe, osx) var httpAgent = require('http-agent'), jsdom = require('jsdom'), sys = require('sys'); var agent = httpAgent.create('www.google.com', ['finance', 'news', 'images']); agent.addListener('next', function (e,agent) {//引数eは必須 var window = jsdom.jsdom(agent.body).createWindow(); jsdom.jQueryify(window, function (window) {//callbackの引数 // jQuery is now loaded on the jsdom window created from 'agent.body' window.jQuery("a").each(function () {console.log(window.jQuery(this).text())});//window.jQuery agent.next(); }); }); agent.addListener('stop', function (agent) { sys.puts('the agent has stopped'); }); agent.start();