puede phantomjs trabajar con node.js?

Me gustaría usar phantomjs en mi script node.js. hay una biblioteca phantomjs-node … pero desafortunadamente el autor usó este extraño código de script de café para explicar lo que está haciendo:

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

ahora si fuera a usar phantomjs directamente con javascript, se vería algo como esto :

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

así que básicamente estoy tratando de escribir el equivalente al primer fragment de código anterior en javascript normal (leyendo la documentation del script de café … esto es lo que hice:

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

lamentablemente no está funcionando! Si corro

 node phantomTest.js 

en el caparazón, nada sucede … nada regresa y el process no se detiene … ¿Alguna idea?

actualizar:

Acabo de leer esto en la faq de phantomjs:

P: ¿Por qué PhantomJS no está escrito como module Node.js?

A: La respuesta corta: "Nadie puede servir a dos maestros".

Una explicación más larga es la siguiente.

A partir de ahora, es técnicamente muy difícil hacerlo.

Cada module de Node.js es esencialmente "un esclavo" del núcleo de Node.js, es decir, "el maestro". En su estado actual, PhantomJS (y su WebKit incluido) necesita tener el control total (en una materia sincrónica) sobre todo: bucle de events, stack de networking y ejecución de JavaScript.

Si la intención es utilizar PhantomJS directamente desde un script que se ejecuta dentro de Node.js, se puede lograr un "enlace libre" iniciando un process PhantomJS e interactuando con él.

mmm … ¿podría esto tener algo que ver con eso? ¡pero entonces toda esa biblioteca no tendría sentido!

actualización 2:

Encontré este código en la web que hace lo mismo:

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

desafortunadamente eso tampoco funciona … ¡el mismo resultado!

phantomjs-node no es un package npm admitido oficialmente para phantomjs. En su lugar, implementa un "puente ingeniosamente nauseabundo" entre el nodo y el fantasma al crear un server web que usa websockets para servir como un canal IPC entre el nodo y el fantasma. No estoy inventando esto

Así que nos comunicamos con PhantomJS girando una instancia de ExpressJS, abriendo Phantom en un subprocess y apuntándolo a una página web especial que convierte los posts de socket.io en llamadas de alerta (). Esas llamadas de alerta () son recogidas por Phantom y ¡listo!

Así que no me sorprendería si phantomjs-node funciona, no funciona, falla silenciosamente o falla espectacularmente. Tampoco esperaría que nadie más que el autor de phantomjs-node pueda resolver problemas de phantomjs-node.

La respuesta a su pregunta original es la respuesta de la pregunta de fantasma: No. El fantasma y el nodo tienen diferencias irreconciliables. Ambos esperan tener un control total sobre la funcionalidad básica de bajo nivel, como el bucle de events, la stack de networking y la ejecución de JS, por lo que no pueden cooperar dentro del mismo process.

También podrías probar phridge . Su ejemplo se habría escrito así:

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

Ahora soy el nuevo mantenedor phantom-node package phantom-node . Ya no usa coffeescript. Puedes hacer 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(); }); }); }); }); 

La nueva versión es mucho más rápida y resistente. Además, ya no usa websockets.

cambie su código a esto, y 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(); }); }); }); }); 

Podrías deshacerse de PhantomJS como yo lo hice porque era demasiado doloroso con estas envolturas que no funcionaban bien, e ir con Zombie.js, que también es bastante popular.

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

Pero estoy tratando de generar una página html con algún file de script externo. No puede inyectar un file de script. Intenté seguir. La callback no regresa desde la línea 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(); }); }); }); }); 

Experimenté los mismos problemas que tú, y aparentemente, hay un problema conocido con phantomjs-node y las versiones más nuevas de nodejs. Parece que dejó de funcionar en algún lugar alnetworkingedor del nodo 0.9.3, de acuerdo con los comentarios del problema. Hasta que se haya resuelto eso, o bien tiene que degradar nodejs, o probar con un module diferente, como node-phantom , o simplemente usar exec/spawn .