28

我想在我的 node.js 脚本中使用 phantomjs。有一个phantomjs-node库.. 但不幸的是作者使用这个奇怪的咖啡脚本代码来解释他在做什么:

phantom = require 'phantom'

phantom.create (ph) ->
  ph.createPage (page) ->
    page.open "http://www.google.com", (status) ->
      console.log "opened google? ", status
      page.evaluate (-> document.title), (result) ->
        console.log 'Page title is ' + result
        ph.exit()

现在如果我直接使用 phantomjs 和 javascript,它看起来像这样

var page = require('webpage').create();
page.open(url, function (status) {
    var title = page.evaluate(function () {
        return document.title;
    });
    console.log('Page title is ' + title);
});

所以基本上我正在尝试用普通的javascript编写相当于上面第一段代码的代码(通过阅读咖啡脚本文档..这就是我所做的:

// file name: phantomTest.js

var phantom = require('phantom');

phantom.create(function(ph) {
    ph.createPage(function(page) {
        page.open('http://www.google.com', function(status) {
            console.log('opened google?', status);
            var title = page.evaluate(function() {
                return document.title;
            });
            console.log('page title is ' + title);              
        });
    });
    ph.exit();
});

不幸的是,它不起作用!如果我跑

node phantomTest.js

在外壳上,什么都没有发生..没有任何回报,过程也没有停止..有什么想法吗?

更新:

我刚刚在 phantomjs常见问题解答中读到了这个:

问:为什么 PhantomJS 不写成 Node.js 模块?

A:简短的回答:“没有人可以侍奉两个主人。”

更长的解释如下。

到目前为止,这样做在技术上非常具有挑战性。

每个 Node.js 模块本质上都是 Node.js 核心的“从属”,即“主控”。在当前状态下,PhantomJS(及其包含的 WebKit)需要对所有内容(以同步方式)进行完全控制:事件循环、网络堆栈和 JavaScript 执行。

如果意图只是直接从 Node.js 中运行的脚本中使用 PhantomJS,则可以通过启动 PhantomJS 进程并与之交互来实现这种“松散绑定”。

嗯..这可能与它有关吗?但是那样整个图书馆就没有意义了!

更新2:

我在网上找到了这个做同样事情的代码:

var phantom = require('phantom');
phantom.create(function(ph) {
  return ph.createPage(function(page) {
    return page.open("http://www.google.com", function(status) {
      console.log("opened google? ", status);
      return page.evaluate((function() {
        return document.title;
      }), function(result) {
        console.log('Page title is ' + result);
        return ph.exit();
      });
    });
  });
});

不幸的是,这也不起作用..同样的结果!

4

7 回答 7

40

phantomjs-node 不是官方支持的 phantomjs 的 npm 包。相反,它通过创建一个使用 websockets 作为节点和 phantom 之间的 IPC 通道的 web 服务器,在 node 和 phantom 之间实现了一个“非常聪明的桥梁”。我不是在编造这个

因此,我们通过启动 ExpressJS 的实例、在子进程中打开 Phantom 并将其指向将 socket.io 消息转换为 alert() 调用的特殊网页来与 PhantomJS 进行通信。那些 alert() 调用由 Phantom 接听,然后就可以了!

因此,如果 phantomjs-node 工作、不工作、静默失败或严重失败,我不会感到惊讶。除了 phantomjs-node 的作者之外,我也不希望任何人能够对 phantomjs-node 进行故障排除。

您最初问题的答案是 phantomjs 常见问题解答中的答案:不。Phantom 和节点具有不可调和的差异。两者都希望完全控制基本的低级功能,如事件循环、网络堆栈和 JS 执行,因此它们不能在同一个进程中协作。

于 2013-04-01T15:20:13.253 回答
9

你也可以试试phridge。你的例子应该是这样写的:

var phantom;

// spawn a new PhantomJS process
phridge.spawn()
    .then(function (ph) {
        phantom = ph;
        return phantom.openPage("http://www.google.com");
    })
    .then(function (page) {
        return page.run(function () {
            // this function runs inside PhantomJS with this bound to a webpage instance
            return this.title;
        });
    })
    .then(function (title) {
        console.log('Page title is ' + title);
        // terminates the process cleanly
        phantom.dispose();
    });
于 2014-05-26T14:34:49.813 回答
9

我现在是phantom-node包的新维护者。它不再使用咖啡脚本了。你可以做类似的事情

var phantom = require('phantom');

phantom.create().then(function(ph) {
  ph.createPage().then(function(page) {
    page.open('https://stackoverflow.com/').then(function(status) {
      console.log(status);
      page.property('content').then(function(content) {
        console.log(content);
        page.close();
        ph.exit();
      });
    });
  });
});

新版本更快、更有弹性。它也不再使用 websockets。

于 2016-02-19T02:24:05.390 回答
1

将您的代码更改为此,它将起作用:

 var phantom = require('phantom');
 phantom.create(function(ph) {
   ph.createPage(function(page) {
     page.open("http://www.google.com", function(status) {
       console.log("opened google? ", status);
       page.evaluate((function() {
         return document.title;
       }), function(result) {
         console.log('Page title is ' + result);
         ph.exit();
       });
     });
   });
 });
于 2013-12-26T16:24:47.560 回答
1

你可以像我一样抛弃 PhantomJS,因为这些包装器不能很好地工作实在是太痛苦了,而使用也很受欢迎的Zombie.js 。

于 2015-04-08T20:21:24.890 回答
1

似乎这是工作..

var phantom = require('phantom');

phantom.create().then(function(ph) {
  ph.createPage().then(function(page) {
    page.open('https://stackoverflow.com/').then(function(status) {
      console.log(status);
      page.property('content').then(function(content) {
        console.log(content);
        page.close();
        ph.exit();
      });
    });
  });
});

但我正在尝试使用一些外部脚本文件生成一个 html 页面。它无法注入脚本文件。我试过如下。回调没有从线路返回page.injectJs('./jQuery.min.js',function() {

var phantom = require('phantom');

    phantom.create().then(function(ph) {
      ph.createPage().then(function(page) {
        page.injectJs('./jQuery.min.js', function() {
          page.property('content').then(function(content) {
            console.log(content);
            page.close();
            ph.exit();
          });
        });
      });
    });
于 2016-11-23T18:12:31.530 回答
0

我遇到了和你一样的问题,显然,nodejs 和较新版本存在一个已知问题。phantomjs-node根据问题中的评论,它似乎在节点 0.9.3 附近停止工作。所以在解决这个问题之前,你要么必须降级 nodejs,要么尝试不同的模块,比如node-phantom,或者只使用exec/spawn.

于 2013-05-01T18:15:47.490 回答