3

情况:

我想在我的 vps ubuntu 服务器上运行一些应用程序以进行爬网测试。我的应用程序使用包管理器meteor-router的“气氛” 。mrt在我安装了 phantomjs 的本地 mac os x 10.8 上brew,一切正常。通过添加,我得到了我页面的漂亮快照

http://sample.com/?_escaped_fragment_=

到网址。

问题:

让我们在我的 ubuntu vps 服务器上尝试同样的方法。2种方式:

1)将未捆绑的应用程序复制到服务器并使用mrt run命令运行它:它工作不稳定。有时它呈现正常。但有时我的动态内容是空白的。就像我的数据库是空的。

2) 将未捆绑的应用程序复制到服务器和mrt bundle fname.tgz它,然后解压缩 .tgz 并main.js使用节点运行它。这种方式可蜘蛛工作绝对错误。每次尝试时,我都会得到空白而不是动态数据。

我的想法:

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

有什么建议么?

4

2 回答 2

2

我想我解决了这个问题。这确实是 spiderable.js 文件中的一个问题。这个模块在 REPL 状态下运行 phantomjs 并通过标准输入给他这样的代码:

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 条件都通过时,它认为 page.content 已 100% 更新。但事实并非如此。我找到并测试的解决方案是将if块包裹起来setTimeout(500ms 对我来说很好):

  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);
  }
于 2013-01-26T00:29:51.250 回答
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回调是在适当的时间调用的

于 2015-05-01T16:22:42.980 回答