webentwicklung-frage-antwort-db.com.de

können phantomjs mit node.js funktionieren?

Ich möchte phantomjs in meinem node.js-Skript verwenden. Es gibt eine phantomjs-node library .. aber leider verwendete der Autor diesen komischen Kaffeeskriptcode, um zu erklären, was er tut:

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

wenn ich jetzt Phantomjs direkt mit Javascript verwenden würde, würde es ungefähr so ​​aussehen: 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);
});

im Grunde versuche ich, das Äquivalent des ersten Code-Snippets oben in normalem Javascript aufzuschreiben (durch das Lesen des Kaffeeskripts Dokumentation .. Folgendes habe ich getan:

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

leider funktioniert es nicht! Wenn ich renne

node phantomTest.js

auf der Shell passiert nichts .. nichts kehrt zurück und der Prozess hört nicht auf .. irgendwelche Ideen?

update:

Ich habe das gerade in den phantomjs faq gelesen: 

F: Warum wird PhantomJS nicht als Node.js-Modul geschrieben?

A: Die kurze Antwort: "Niemand kann zwei Herren dienen."

Eine längere Erklärung lautet wie folgt.

Ab jetzt ist es technisch sehr anspruchsvoll.

Jedes Node.js-Modul ist im Wesentlichen "Slave" für den Kern von Node.js "der Meister". In seinem aktuellen Status muss PhantomJS (und das enthaltene WebKit) die vollständige Kontrolle (in einer synchronen Angelegenheit) über .__ haben. alles: Ereignisschleife, Netzwerkstack und JavaScript-Ausführung.

Wenn es sich nur um die Verwendung von PhantomJS handelt, direkt von einem Skript aus Eine solche "lose Bindung" kann innerhalb von Node.js ausgeführt werden, indem einen PhantomJS-Prozess starten und damit interagieren.

mmm .. könnte das etwas damit zu tun haben? Aber dann würde diese ganze Bibliothek keinen Sinn machen!

update 2:

Ich habe diesen Code im web gefunden, der dasselbe tut:

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

das funktioniert leider auch nicht .. gleiches Ergebnis!

28
abbood

phantomjs-node ist kein offiziell unterstütztes npm-Paket für phantomjs. Stattdessen wird eine "vernünftig clevere Brücke" zwischen Knoten und Phantom implementiert, indem ein Webserver erstellt wird, der Websockets verwendet, um als IPC Kanal zwischen Knoten und Phantom zu dienen. Ich mache mir das nicht ein :

Daher kommunizieren wir mit PhantomJS, indem wir eine Instanz von ExpressJS aufdrehen, Phantom in einem Unterprozess öffnen und auf eine spezielle Webseite zeigen, die socket.io-Meldungen in alert () - Aufrufe umwandelt. Diese Alarmrufe werden von Phantom entgegengenommen und los geht's!

Daher wäre ich nicht überrascht, wenn der Phantomjs-Knoten funktioniert, nicht funktioniert, im Hintergrund ausfällt oder spektakulär ausfällt. Ich würde auch nicht erwarten, dass jemand anderes als der Autor des Phantomjs-Knotens Phantomjs-Knoten behandeln kann.

Die Antwort auf Ihre ursprüngliche Frage ist die Antwort aus der Phantom-Frage: Nein. Phantom und Knoten haben unüberbrückbare Unterschiede. Beide erwarten vollständige Kontrolle über grundlegende grundlegende Funktionen wie die Ereignisschleife, den Netzwerkstack und die JS-Ausführung, sodass sie nicht innerhalb desselben Prozesses zusammenarbeiten können.

39
Rein Henrichs

Ich bin jetzt der neue Betreuer für phantom-node-Paket. Es verwendet kein Kaffeescript mehr. Sie können so etwas tun

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

Die neue Version ist viel schneller und belastbarer. Es verwendet auch keine Websockets mehr. 

9
Amir Raminfar

Sie könnten auch phridge versuchen. Dein Beispiel wäre so geschrieben worden:

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

Sie könnten PhantomJS einfach so aufgeben, wie ich es tat, weil es einfach zu schmerzhaft war, wenn diese Wrapper nicht gut funktionieren, und gehen Sie mit Zombie.js , was auch ziemlich beliebt ist.

1
PositiveGuy

Ändern Sie Ihren Code so, und es wird funktionieren:

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

Scheint das funktioniert ..

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

Ich versuche jedoch, eine HTML-Seite mit einer externen Skriptdatei zu erstellen. Es kann keine Skriptdatei eingefügt werden. Ich versuchte es wie folgt. Callback kehrt nicht von der Zeile page.injectJs('./jQuery.min.js',function() { zurück 

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

Ich habe die gleichen Probleme wie Sie erlebt und anscheinend gibt es ein Bekanntes Problem mit phantomjs-node und neueren Versionen von nodejs. Es scheint, als ob es irgendwo um den Knoten 0.9.3 herum aufgehört hat, laut den Kommentaren in der Ausgabe. Bis dies behoben ist, müssen Sie entweder nodejs downgraden oder ein anderes Modul wie node-phantom ausprobieren oder einfach exec/spawn verwenden.

0
NilsH