pode phantomjs trabalhar com node.js?

Eu gostaria de usar o phantomjs no meu script node.js. existe uma biblioteca de nós do phantomjs .. mas infelizmente o autor usou esse estranho código de script de café para explicar o que ele está fazendo:

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

Agora, se eu fosse usar o phantomjs diretamente com o javascript, seria algo parecido com isto :

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

Então, basicamente, eu estou tentando escrever o equivalente do primeiro trecho de código acima no javascript normal (lendo a documentação do script de café … isso é o que eu fiz:

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

infelizmente não está funcionando! Se eu corro

 node phantomTest.js 

na concha, nada acontece … nada volta e o processo não pára … alguma ideia?

atualizar:

Acabei de ler isso no phantomjs faq :

P: Por que o PhantomJS não está escrito como módulo Node.js?

A: A resposta curta: “Ninguém pode servir dois mestres.”

Uma explicação mais longa é a seguinte.

A partir de agora, é tecnicamente muito desafiador fazê-lo.

Cada módulo do Node.js é essencialmente “um escravo” para o núcleo do Node.js, ou seja, “o mestre”. Em seu estado atual, o PhantomJS (e seu WebKit incluído) precisa ter o controle total (em uma questão síncrona) sobre tudo: loop de events, pilha de rede e execução de JavaScript.

Se a intenção é apenas usar o PhantomJS diretamente de um script em execução dentro do Node.js, tal “binding frouxa” pode ser obtida iniciando um processo do PhantomJS e interagindo com ele.

mmm .. isso poderia ter algo a ver com isso? mas então toda essa biblioteca não faria sentido!

atualização 2:

Eu encontrei este código na web que faz a mesma coisa:

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

infelizmente isso não está funcionando também .. mesmo resultado!

O phantomjs-node não é um pacote npm oficialmente suportado para phantomjs. Em vez disso, implementa uma “ponte náusea inteligente” entre o nó e o fantasma criando um servidor da Web que usa websockets para servir como um canal IPC entre o nó e o fantasma. Eu não estou inventando isso :

Assim, nos comunicamos com o PhantomJS girando uma instância do ExpressJS, abrindo o Phantom em um subprocess e apontando-o em uma página especial que transforma as mensagens do socket.io em chamadas do alert (). Essas chamadas de alerta () são captadas pelo Phantom e lá vai você!

Então eu não ficaria surpreso se o nó phantomjs funcionar, não funcionar, falhar silenciosamente ou falhar espetacularmente. Também não esperaria que alguém além do autor do nó phantomjs fosse capaz de solucionar problemas do nó phantomjs.

A resposta à sua pergunta original é a resposta do phantomjs faq: Não. O fantasma e o nó têm diferenças irreconciliáveis. Ambos esperam ter controle total sobre funcionalidades fundamentais de baixo nível, como o loop de events, a pilha de rede e a execução de JS, para que não possam cooperar no mesmo processo.

Você também pode experimentar o phridge . Seu exemplo teria sido escrito assim:

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

Agora sou o novo mantenedor phantom-node pacote phantom-node . Não usa mais o coffeescript. Você pode fazer algo como

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

A nova versão é muito mais rápida e resiliente. Ele também não usa mais websockets.

mude seu código para isso, e estará funcionando:

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

Você poderia simplesmente abandonar o PhantomJS como eu fiz porque era muito doloroso, com esses invólucros não funcionando bem, e ir com o Zombie.js, que é bastante popular também.

Parece que isso está funcionando ..

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

Mas estou tentando gerar uma página html com algum arquivo de script externo. Não é possível injetar um arquivo de script. Eu tentei seguir. O retorno de page.injectJs('./jQuery.min.js',function() { não está retornando da linha 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(); }); }); }); }); 

Eu tive os mesmos problemas que você e, aparentemente, há um problema conhecido com o phantomjs-node e versões mais recentes do nodejs. Parece que parou de funcionar em algum lugar próximo ao nó 0.9.3, de acordo com os comentários da edição. Então, até que isso seja resolvido, você terá que fazer o downgrade do nodejs, ou tentar um módulo diferente, como node-phantom , ou apenas usar exec/spawn .