2013-04-01 3 views
27

Я хотел бы использовать phantomjs в моем скрипте node.js. есть phantomjs-node библиотека .. но, к сожалению, автор использовал этот странный код кофе сценарий, чтобы объяснить, что он делает:Может ли phantomjs работать с node.js?

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 (прочитав сценарий кофе documentation .. это то, что я сделал:

// 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 прямо из сценария работает в 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(); 
     }); 
    }); 
    }); 
}); 

, к сожалению, не работает либо .. тот же результат!

+3

Вызова что-то «немой», потому что вы не понимаете, как это работает и/или вы не можете сделать его работать в вашем случае является простым грубым. –

+2

Кроме того, есть https://github.com/sheebz/phantom-proxy, который более рекомендуется, чем другие мосты Node.js. Люди используют мост PhantomJS с Ruby, PHP, Node.js с переменным успехом. –

+3

Прошу прощения за мою сильную формулировку, я возьму ее из вопроса. Я также посмотрю на «phantom-proxy». В конце дня моя цель - заставить все работать, это не умалять усилия других людей. – abbood

ответ

38

phantomjs-node не является официальным поддерживаемым пакетом npm для phantomjs. Вместо этого он реализует «тошнотворный умный мост» между узлом и фантомом, создавая веб-сервер, который использует веб-порты, чтобы служить каналом IPC между узлом и фантомом.I'm not making this up:

Так мы общаемся с PhantomJS путем раскручивания экземпляра ExpressJS, открывая Фантом в подпроцессе, и указывая его на специальную веб-странице, которая превращает Socket.io сообщения в боевую готовность() вызывает. Те сигналы alert() вызываются Phantom, и вот вы идете!

Поэтому я не удивлюсь, если работает phantomjs-node, не работает, терпит неудачу или не срабатывает эффектно. Я также не ожидал, что кто-либо, кроме автора узла phantomjs, сможет устранить неисправность phantomjs-node.

Ответ на ваш первоначальный вопрос - ответ от faantomjs faq: Нет. Фантом и узел имеют непримиримые различия. Оба ожидают полного контроля над фундаментальными низкоуровневыми функциями, такими как цикл событий, сетевой стек и выполнение JS, поэтому они не могут взаимодействовать в рамках одного и того же процесса.

+5

ничего себе! поэтому следующий вопрос: какой лучший способ очистить динамическую страницу с помощью jquery? – abbood

+0

@abbood Я не думаю, что это возможно.Какова ваша цель? –

+1

почему бы и нет? я думаю, что нашел свой [ответ] (https://github.com/tmpvar/jsdom/), хотя .. как всегда .. Я начинаю с невозможного жесткого маршрута, только чтобы найти гораздо более легкое решение lol .. i ' Я дам вам правильную награду за ответ. – abbood

0

Я испытал те же проблемы, что и вы, и, по-видимому, есть known issue с phantomjs-node и более новыми версиями nodejs. Похоже, что он прекратил работать где-то вокруг узла 0.9.3, согласно комментариям в этом выпуске. Таким образом, пока это не будет разрешено, вам либо придется отказаться от nodejs, либо попробовать другой модуль, например node-phantom, или просто использовать exec/spawn.

1

изменить свой код к этому, и он будет работать:

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

Вы также могли бы дать 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(); 
    }); 
1

Вы можете просто угробить PhantomJS, как я сделал, потому что это было слишком много боли с этими обертками не работает хорошо, и идти с Zombie.js который является довольно популярным тоже.

9

Я теперь новый сопровождающий для 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(); 
     }); 
    }); 
    }); 
}); 

Новая версия намного быстрее и упруго. Он также больше не использует веб-сайты.

1

Кажется, это работает ..

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-страницу с каким-либо внешним файлом сценария. Он не может вставить файл сценария. Я пробовал как следует. Обратный вызов не возвращается из линии 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(); 
      }); 
     }); 
     }); 
    }); 
Смежные вопросы