2013-04-01 87 views
27

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

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,它会看起来像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的第一个片段的当量(通过读取咖啡脚本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(); 
}); 

不幸的是它不工作!如果我在shell中运行

node phantomTest.js 

,没有任何反应..没有回报和进程不会停止..任何想法?

更新:

我刚才读这在phantomjs faq

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

答:答案很简单:“一个人不能事奉两个主。”

更长的解释如下。

截至目前,这在技术上非常具有挑战性。

每个Node.js的模块本质上是“从属”到的Node.js, 即,“主”的核心。在目前的状态下,PhantomJS(及其包含的 WebKit)需要完全控制(在同步问题中)所有事件:事件循环,网络堆栈和JavaScript执行。

如果意图只是使用在Node.js中运行的脚本 来使用PhantomJS,那么可以通过启动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(); 
     }); 
    }); 
    }); 
}); 

可惜就是不工作或者..同样的结果!

+3

返回调用一些“愚蠢”,因为你不知道它是如何工作和/或你不能让你的情况是工作很粗鲁。 –

+2

另外,还有比其他Node.js网桥更受推荐的https://github.com/sheebz/phantom-proxy。人们一直在使用Ruby,PHP和Node.js桥接PhantomJS,并取得了不同的成功。 –

+3

对于我强烈的措辞表示歉意,我会从这个问题中提出来。我还会看看'phantom-proxy' ..在这一天结束时,我的目标是让事情有效,它是不要贬低别人的努力。 – abbood

回答

38

phantomjs节点不是一个官方支持NPM包phantomjs。相反,它通过创建一个使用websocket作为节点和幻像之间的IPC通道的Web服务器,在节点和幻像之间实现了一个“恶心的巧妙桥梁”。I'm not making this up

所以我们通过旋转起来ExpressJS的一个实例,在子进程打开幻影,并在一个特殊的网页,轮流socket.io消息进入警戒指向它()调用与PhantomJS沟通。那些alert()调用被Phantom拾起,你去了!

所以我不会惊讶,如果phantomjs节点的工作,不工作,失败默默,或失败壮观。我也不希望除phantomjs-node的作者以外的任何人能够对phantomjs-node进行故障排除。

您的原始问题的答案是phantomjs faq的答案:不。幻影和节点有不可调和的差异。它们都希望完全控制事件循环,网络堆栈和JS执行等基本底层功能,因此它们不能在同一个进程中合作。

+5

哇,这很讨厌!那么接下来的问题是:用jquery刮动态页面的最佳方式是什么? – abbood

+0

@abbood我不认为这是可能的。你的目标是什么? –

+1

为什么不可能?虽然..我一直认为我找到了我的[答案](https://github.com/tmpvar/jsdom/)..我一开始就采取不可能的艰难路线,只是为了找到一个更简单的解决方案大声笑..我'你会给你正确的答案奖励。 – abbood

0

我遇到了同样的问题,显然,known issuephantomjs-node和更新版本的nodejs。根据问题中的评论,似乎它在节点0.9.3附近停止工作。因此,在解决问题之前,您必须降级nodejs,或者尝试使用其他模块,例如node-phantom或仅使用exec/spawn

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

你可以只沟PhantomJS像我一样,因为它只是太多与这些包装都不尽如人意疼痛,并与Zombie.js这是非常流行的太去。

9

我现在是phantom-node包的新维护者。它不再使用coffeescript。你可以做类似于

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。

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(); 
      }); 
     }); 
     }); 
    }); 
相关问题