Может ли phantomjs работать с node.js?
Я хотел бы использовать phantomjs в моем node.js script. есть библиотека phantomjs-node, но, к сожалению, автор использовал этот странный код кофе script, чтобы объяснить, что он делает:
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 (читая кофе script документацию.. это это то, что я сделал:
// 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();
});
К сожалению, он не работает! Если я запустил
node phantomTest.js
на оболочке ничего не происходит.. ничего не возвращается и процесс не останавливается.. любые идеи?
обновление:
Я просто прочитал это в phantomjs faq:
Q: Почему PhantomJS не написан как модуль node.js?
A: Короткий ответ: "Никто не может служить двум мастерам".
Более длинное объяснение выглядит следующим образом.
В настоящее время технически очень сложно это сделать.
Каждый модуль node.js по существу является "подчиненным" в ядре node.js, т.е. "хозяин". В своем текущем состоянии PhantomJS (и включенный в него WebKit) должен иметь полный контроль (в синхронном режиме) все: цикл событий, сетевой стек и выполнение JavaScript.
Если намерение заключается в использовании PhantomJS прямо из scriptработающий в пределах node.js, такое "свободное связывание" может быть достигнуто посредством запуск процесса PhantomJS и взаимодействие с ним.
mmm.. может ли это иметь к этому какое-то отношение? но тогда вся эта библиотека не имеет смысла!
обновление 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();
});
});
});
});
к сожалению, что не работает либо.. тот же результат!
Ответы
Ответ 1
phantomjs- node не является официальным поддерживаемым пакетом npm для phantomjs. Вместо этого он реализует "тошнотворный умный мост" между node и phantom, создавая веб-сервер, который использует веб-порты для использования в качестве канала IPC между node и phantom. Я не делаю это:
Итак, мы общаемся с PhantomJS, создавая экземпляр ExpressJS, открывая phantom в подпроцессе и указывая его на специальную веб-страницу, которая превращает сообщения socket.io в вызовы alert(). Эти вызовы alert() подхватываются phantom и там вы идете!
Так что я не удивлюсь, если phantomjs- node работает, не работает, терпит неудачу или не срабатывает эффектно. Я также не ожидал, что кто-либо, кроме автора фантомов - node, сможет устранить ошибки phantomjs- node.
Ответ на ваш первоначальный вопрос - это ответ из фантомов faq: № phantom и node имеют непримиримые различия. Оба ожидают полного контроля над фундаментальными низкоуровневыми функциями, такими как цикл событий, сетевой стек и выполнение JS, поэтому они не могут взаимодействовать в рамках одного и того же процесса.
Ответ 2
Вы также можете попробовать 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();
});
Ответ 3
Теперь я являюсь новым сопровождающим для пакета 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();
});
});
});
});
Новая версия намного быстрее и эластична. Он также больше не использует веб-сайты.
Ответ 4
измените код на это, и он будет работать:
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();
});
});
});
});
Ответ 5
Вы могли бы просто расколоть PhantomJS так же, как и я, потому что это было слишком больно, когда эти обертки не работали хорошо, и пошли с Zombie.js, который также очень популярен.
Ответ 6
Кажется, это работает.
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-страницу с каким-то внешним файлом script. Он не может вставить файл script. Я пробовал как следует. Обратный вызов не возвращается из строки 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();
});
});
});
});
Ответ 7
Я столкнулся с теми же проблемами, что и вы, и, по-видимому, существует известная проблема с phantomjs-node
и более новыми версиями nodejs. Похоже, что он прекратил работать где-то около node 0.9.3, согласно комментариям в этом выпуске. Итак, до тех пор, пока это не будет разрешено, вам придется либо отказаться от nodejs, либо попробовать другой модуль, например node-phantom, или просто использовать exec/spawn
.