使用jsdom和node.js发布表单

时间:2011-06-07 09:08:30

标签: jquery node.js jsdom

我正在使用jsdom,jquery和node.js来抓取网站。有什么办法可以使用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'),必须抓取生成的页面。

有人可以帮忙吗? 感谢

2 个答案:

答案 0 :(得分:21)

哦,伙计。这是我们进入疯狂土地的地方。

目前,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情况。

答案 1 :(得分:0)

您需要类似:https://github.com/driverdan/node-XMLHttpRequest之类的内容,并且您需要设置jsdom以将其用于ajax类型请求。我还没有在野外看到过这种用途,但理论上它应该是可能的。

另一种方法是直接根据http库(或请求,您似乎依赖的请求)上的节点自行发布帖子。

或者: https://github.com/mikeal/request/blob/master/main.js#L357

http://nodejs.org/docs/v0.4.8/api/http.html#http.request方法POST

约什