【问题标题】:can phantomjs work with node.js?phantomjs 可以与 node.js 一起使用吗?
【发布时间】:2013-03-22 15:25:17
【问题描述】:

我想在我的 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()

现在如果我直接在 javascript 中使用 phantomjs,它看起来像 this:

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 编写与上面第一个 sn-p 代码等效的代码(通过阅读咖啡脚本 documentation.. 这就是我所做的:

// 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

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

更新:

我刚刚在phantomjsfaq读到这个:

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

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

更详细的解释如下。

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

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

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

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

更新 2:

我在web 中发现了这个代码,它做同样的事情:

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();
      });
    });
  });
});

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

【问题讨论】:

  • 因为你不明白它是如何工作的和/或你不能让它在你的情况下工作而称它为“愚蠢”是很粗鲁的。
  • 另外,github.com/sheebz/phantom-proxy 比其他 Node.js 桥更推荐。人们一直在使用 PhantomJS 与 Ruby、PHP、Node.js 进行桥接,并取得了不同程度的成功。
  • 我为我的措辞强硬表示歉意,我会从问题中删除它。我还会看看phantom-proxy.. 在一天结束时,我的目标是把事情做好,不是贬低别人的努力。
  • 这是过时的,应该被编辑或删除。它不反映最新的 phantomjs-node 包及其功能。

标签: javascript jquery node.js coffeescript phantomjs


【解决方案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();
          });
        });
      });
    });

【讨论】:

    【解决方案2】:

    我现在是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。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        你也可以试试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();
            });
        

        【讨论】:

          【解决方案5】:

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

           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();
                 });
               });
             });
           });
          

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              phantomjs-node 不是官方支持的 phantomjs 的 npm 包。相反,它通过创建一个使用 websockets 作为节点和 phantom 之间的 IPC 通道的 Web 服务器,在 node 和 phantom 之间实现了一个“非常聪明的桥梁”。 I'm not making this up:

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

              因此,如果 phantomjs-node 工作、不工作、静默失败或严重失败,我不会感到惊讶。我也不希望除了 phantomjs-node 的作者之外的任何人都能够解决 phantomjs-node 的问题。

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

              【讨论】:

              • 哇,这太恶心了!那么接下来的问题是:使用 jquery 抓取动态页面的最佳方法是什么?
              • @abbood 我认为这不可能。你在这里的目标是什么?
              • 为什么不可能?我想我找到了我的answer 虽然.. 一如既往.. 我从走一条不可能的艰难路线开始,只是为了找到一个更容易的解决方案哈哈.. 我会给你正确答案奖..
              • 如果你在 jQuery 中嵌入一个完整的 DOM 和 JS 运行时实现是可能的,但我认为这不是一个可行的解决方案。
              • 是的!它现在对我来说就像一个魅力......只需将你的原始 html 转储到一个 Dom 结构中......使用 jquery 魔法来遍历它......每个人都很开心!看看我对上述问题的愤怒更新;)
              猜你喜欢
              • 1970-01-01
              • 2013-05-24
              • 1970-01-01
              • 1970-01-01
              • 2018-05-17
              • 2012-01-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多