読者です 読者をやめる 読者になる 読者になる

以下斜め読んだ内容

pseudo translation of useful posts, book reviews, remarks,etc. twitter: feeddict

Charlie Robbins「jsdom.jsとjquery使ったスクレピング」

斜め読み

nodejitsu.com 2010.9.24のエントリ

jsdom + jQuery in 5 lines with node.js

という内容のエントリ
サンプルコード修正しないと動かない

以下斜め読んだ内容
//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モジュールで各コードはやや冗長
    • requesthttp-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();