11

jsdom、jquery、node.jsを使用してWebサイトをスクレイプしています。jsdomを使用してフォームを投稿し、結果の次のページウィンドウを取得する方法はありますか?

これがコードです

var httpAgent = require('http-agent'),
    jsdom = require('jsdom'),
    request = require('request');

request({uri:'http://www.orbitz.com'}, function(error, response, body){
  if(error && response.statusCode != 200)
    console.log('Error on request');

  jsdom.env({
    html: body,
      scripts : [
        'http://code.jquery.com/jquery-1.5.min.js'
      ]
    }, function(err, window) {
          var $ = window.jQuery;

          $('#airOneWay').attr('checked', true);
          $('#airRoundTrip').removeAttr('checked');
          $('#airOrigin').val('ATL');
          $('#airDestination').val('CHI');

          // here we need to submit the form $('#airbotForm') and get the resulting window
          //console.log($('#airbotForm').html());
   });
});

これは送信する必要のあるフォームで$('#airbotForm')あり、結果のページをキャプチャする必要があります。

誰か助けてもらえますか?ありがとう

4

2 に答える 2

22

ちょっと、あなた。これは私たちがクレイジーな土地に入るところです。

現状では、jsdomと「ブラウザ」の主な違いは、外部からウィンドウにアクセスできることです。たとえば、あなたの例では、に設定$しましたwindow.$。これは、基本的に「ねえ、この現在のウィンドウでは、jqueryオブジェクトへの参照が必要です」と言っています。あなたは10のウィンドウを持ち、それら$のすべてのウィンドウへの参照を保持することができます。

ここで、フォームの送信/リンクのクリックによって新しいページをロードするとします...

JSDOMは、ウィンドウをリロードし、javascriptコンテキストを更新する必要があります(元のjsdom.env呼び出しで提供したスクリプトを挿入する可能性があります)。残念ながら、最後のウィンドウから保持していた参照は消えたり上書きされたりします。つまり、ページがリロードされた後に呼び出すと$(...)、予期しない動作が発生します(メモリリークまたは前のページのdom要素の選択が発生する可能性があります)

これをどのように回避しますか?

すでにjqueryを使用しているので、次のようにします。

var form   = $('#htlbotForm');
var data   = form.serialize();
var url    = form.attr('action') || 'get';
var type   = form.attr('enctype') || 'application/x-www-form-urlencoded';
var method = form.attr('method');

request({
  url    : url,
  method : method.toUpperCase(),
  body   : data,
  headers : {
    'Content-type' : type
  }
},function(error, response, body) {
  // this assumes no error for brevity.
  var newDoc = jsdom.env(body, [/* scripts */], function(errors, window) {
    // do your post processing
  });
});

YMMVですが、このアプローチは非ajaxの状況で機能するはずです。

于 2011-06-10T04:10:26.443 に答える
0

https://github.com/driverdan/node-XMLHttpRequestのようなものが必要であり、ajaxタイプのリクエストに使用するようにjsdomを設定する必要があります。私は実際にこのタイプの使用を見たことがありませんが、理論的には可能であるはずです。

もう1つの方法は、httpライブラリのノード(または依存しているように見えるリクエスト)に基づいて直接投稿を行うことです。

いずれか: https ://github.com/mikeal/request/blob/master/main.js#L357

メソッドPOSTを使用したhttp://nodejs.org/docs/v0.4.8/api/http.html#http.request

ジョシュ

于 2011-06-09T04:14:39.707 に答える