Meteor应用使用Spiderable呈现不稳定

3

情况:

我想在我的vps ubuntu服务器上运行一些应用程序进行爬行测试。 我的应用程序使用来自 'atmosphere' 的 meteor-routermrt包管理器。 在我的本地mac os x 10.8上,使用brew安装的phantomjs一切都很好。通过在url末尾添加

http://sample.com/?_escaped_fragment_=

我可以得到我的页面的快照。

问题:

让我们在我的ubuntu vps服务器上尝试相同的操作,有两种方法:

1)将未打包的应用程序复制到服务器并使用mrt run命令运行它:这种方法不稳定。有时会正常渲染,但是有时我的动态内容为空,就像我的数据库是空的。

2)将未打包的应用程序复制到服务器并将其mrt bundle fname.tgz打包,然后解压缩.tgz并使用node运行其main.js。这种方式 spiderable 完全错误。每次尝试时我都得到空白而不是动态数据。

我的想法:

我的ubuntu机器的内存和处理器资源比我的本地机器要少得多。这就是为什么生成动态内容需要更长的时间,但phantom认为页面已经完成并在meteor渲染之前进行了快照。

有什么建议吗?

2个回答

2

我认为我解决了这个问题。 实际上,这是spiderable.js文件中的问题。 该模块在REPL状态下运行phantomjs,并通过stdin给出如下代码:

var url = '" + url + "';
var page = require('webpage').create();
page.open(url);

setInterval(function() {
  var ready = page.evaluate(function () {
    if (typeof Meteor !== 'undefined'
        && typeof(Meteor.status) !== 'undefined'
        && Meteor.status().connected) {
      Meteor.flush();
      return Meteor._LivedataConnection._allSubscriptionsReady();
    }
    return false;
  });

  if (ready) {
    var out = page.content;
    out = out.replace(/<script[^>]+>(.|\\n|\\r)*?<\\/script\\s*>/ig, '');
    out = out.replace('<meta name=\"fragment\" content=\"!\">', '');

    console.log(out);
    phantom.exit();
  }
}, 100);

问题在于当所有Meteor条件都满足时,它会认为页面内容已经更新完全。但实际上并非如此。我发现并测试的解决方案是用setTimeout(500毫秒)包装if块,这对我来说很有效。
  if (ready) {
    setTimeout(function () {
      var out = page.content;
      out = out.replace(/<script[^>]+>(.|\\n|\\r)*?<\\/script\\s*>/ig, '');
      out = out.replace('<meta name=\"fragment\" content=\"!\">', '');

      console.log(out);
      phantom.exit();
    }, 500);
  }

0

我相信正确的做法是将回调函数传递给page.open,像这样(请参阅文档):

page.open(url, function (status) {
    ...
};

另外,如果你想依赖于超时设置进行快照,我建议缩短超时并将其包装在循环中,以加快速度并使其更可靠:

page.open(url, function (status) {
    if(status !== 'success') {
        phantom.exit();
        return;
    }

    function isReady() {
        return page.evaluate(function () {
            if('undefined' === typeof Meteor
            || 'undefined' === typeof(Meteor.status)
            || !Meteor.status().connected)
                return false;
            Meteor.flush();
            return Meteor._LivedataConnection._allSubscriptionsReady();
        }
    }

    function trySnapshot() {
        if(!isReady()) {
            setTimeout(trySnapshot, 100);
            return;
        }
        console.log(page.content
            .replace(/<script[^>]+>(.|\\n|\\r)*?<\\/script\\s*>/ig, '')
            .replace('<meta name=\"fragment\" content=\"!\">', '')
        );
        phantom.exit();
    }
    trySnapshot();
};

我也认为我的最后一段代码片段经常会在没有超时的情况下执行,因为page.open回调函数在适当的时间被调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接