possono i phantomjs funzionare con node.js?

Vorrei usare phantomjs nel mio script node.js. c’è una libreria di nodes phantomjs .. ma sfortunatamente l’autore ha usato questo strano codice di script per il caffè per spiegare cosa sta facendo:

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

ora se dovessi usare phantomjs direttamente con javascript, sarebbe simile a questo :

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

quindi in pratica sto provando a scrivere l’equivalente del primo frammento di codice sopra in javascript normale (leggendo la documentazione dello script del caffè … questo è quello che ho fatto:

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

sfortunatamente non funziona! Se corro

 node phantomTest.js 

sulla shell, non succede nulla .. non ritorna niente e il processo non si ferma .. qualche idea?

aggiornare:

Ho appena letto questo in faq phantomjs:

D: Perché PhantomJS non è stato scritto come modulo Node.js?

A: La risposta breve: “Nessuno può servire a due padroni”.

Una spiegazione più lunga è la seguente.

A partire da ora, è tecnicamente molto impegnativo farlo.

Ogni modulo Node.js è essenzialmente “uno schiavo” nel nucleo di Node.js, cioè “il maestro”. Allo stato attuale, PhantomJS (e il suo WebKit incluso) deve avere il controllo completo (in una questione sincrona) su tutto: loop eventi, stack di rete e esecuzione JavaScript.

Se l’intenzione è solo utilizzare PhantomJS direttamente da uno script in esecuzione in Node.js, tale “rilegatura libera” può essere ottenuta lanciando un processo PhantomJS e interagendo con esso.

mmm .. questo potrebbe avere qualcosa a che fare con questo? ma allora quella intera biblioteca non avrebbe senso!

aggiornamento 2:

Ho trovato questo codice nel web che fa la stessa cosa:

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

sfortunatamente non funziona neanche .. lo stesso risultato!

phantomjs-node non è un pacchetto npm supportato ufficialmente per phantomjs. Invece, implementa un “ponte nauseamente intelligente” tra nodo e fantasma creando un server web che utilizza websocket per fungere da canale IPC tra nodo e fantasma. Non sto inventando questo :

Quindi comunichiamo con PhantomJS girando un’istanza di ExpressJS, aprendo Phantom in un sottoprocesso e puntandolo su una pagina Web speciale che trasforma i messaggi socket.io in chiamate alert (). Quelle chiamate di avviso () vengono rilevate da Phantom e eccoti!

Quindi non sarei sorpreso se il nodo phantomjs funzionasse, non funzionasse, fallisse silenziosamente o fallisse in modo spettacolare. Né mi aspetterei che qualcuno oltre all’autore di phantomjs-node sia in grado di risolvere il problema del nodo fantasma.

La risposta alla tua domanda originale è la risposta dalla faq di phantomjs: No. Fantasma e nodo hanno differenze inconciliabili. Entrambi si aspettano di avere il controllo completo su funzionalità basilari di basso livello come il ciclo degli eventi, lo stack di rete e l’esecuzione di JS in modo che non possano cooperare all’interno dello stesso processo.

Puoi anche provare con phridge . Il tuo esempio sarebbe stato scritto così:

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

Ora sono il nuovo manutentore phantom-node pacchetto phantom-node . Non usa più il coffeescript. Puoi fare qualcosa del genere

 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 nuova versione è molto più veloce e resiliente. Inoltre non usa più websocket.

cambia il tuo codice e funzionerà:

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

Potresti semplicemente abbandonare PhantomJS come ho fatto perché era troppo doloroso con questi wrapper che non funzionavano bene, e andare con Zombie.js che è anche molto popolare.

Sembra che funzioni

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

Ma sto provando a generare una pagina html con qualche file di script esterno. Non è in grado di iniettare un file di script. Ho provato a seguire. La richiamata non viene restituita dalla riga 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(); }); }); }); }); 

Ho avuto gli stessi problemi che ho riscontrato e, a quanto pare, c’è un problema noto con il phantomjs-node e le versioni più recenti di nodejs. Sembra che abbia smesso di funzionare da qualche parte attorno al nodo 0.9.3, secondo i commenti nel problema. Quindi, finché non è stato risolto, è necessario eseguire il downgrade di nodejs, o provare un modulo diverso, come node-phantom , o semplicemente usare exec/spawn .