Сохраните и визуализируйте веб-страницу с помощью PhantomJS и node.js.

Я ищу пример запроса веб-страницы, ожидания рендеринга JavaScript (JavaScript изменяет DOM), а затем получения HTML-кода страницы.

Это должен быть простой пример с очевидным вариантом использования PhantomJS. Я не могу найти достойный пример, документация, похоже, посвящена использованию командной строки.


person Harry    schedule 01.04.2012    source источник
comment
Вы хотите сделать это на стороне клиента или на стороне сервера?   -  person Declan Cook    schedule 02.04.2012
comment
@DeclanCook на стороне сервера, я думаю? Клиентская сторона потребует от пользователя установить фантом, верно? Что не сработает, если я правильно понимаю. Спасибо   -  person Harry    schedule 02.04.2012
comment
Что вы пытаетесь сделать с html, когда он у вас есть? Пытаюсь понять, чего вы пытаетесь достичь. В Phantomjs есть манипуляции с домом, см. code.google.com/p/phantomjs/wiki/QuickStart. #DOM_Manipulation вы собираетесь это куда-то отправить?   -  person Declan Cook    schedule 02.04.2012
comment
@DeclanCook вариант использования создает кешированную статическую html-копию представления приложения javascript для поисковых систем. Я хочу иметь возможность программно запускать карту сайта и сохранять html-версию каждой ссылки.   -  person Harry    schedule 02.04.2012
comment
@DeclanCook да, эта связанная страница — это то, что мне нужно, мне просто нужен пример того, как это сделать из node. Спасибо   -  person Harry    schedule 02.04.2012
comment
@DeclanCook Значит, сделать это на стороне клиента невозможно?   -  person phabtar    schedule 17.07.2013


Ответы (6)


Судя по вашим комментариям, у вас есть 2 варианта.

  1. Попробуйте найти модуль узла phantomjs - https://github.com/amir20/phantomjs-node
  2. Запустите phantomjs как дочерний процесс внутри узла — http://nodejs.org/api/child_process.html

Редактировать:

Кажется, что дочерний процесс предлагается phantomjs как способ взаимодействия с узлом, см. часто задаваемые вопросы - http://code.google.com/p/phantomjs/wiki/FAQ

Редактировать:

Пример скрипта Phantomjs для получения HTML-разметки страниц:

var page = require('webpage').create();  
page.open('http://www.google.com', function (status) {
    if (status !== 'success') {
        console.log('Unable to access network');
    } else {
        var p = page.evaluate(function () {
            return document.getElementsByTagName('html')[0].innerHTML
        });
        console.log(p);
    }
    phantom.exit();
});
person Declan Cook    schedule 02.04.2012
comment
Можете ли вы показать пример? Захватить страницу, запустить javascript, получить html? - person Harry; 02.04.2012
comment
Вы можете просто использовать «page.content», нет необходимости что-либо оценивать. - person JLarky; 16.07.2012
comment
Это здорово, но... изо всех сил пытается использовать require('веб-страницу') в этом скрипте, обернутом узлом, потому что модуль веб-страницы не определен в узле, он находится в фантоме. У кого-нибудь есть идеи? Является ли «веб-страница» общим модулем как для узла, так и для фантома? Или я могу использовать require в фантомном контексте только как-то? - person Adam Waite; 18.10.2012
comment
@AdamWaite оценка изолирована и не может выполнить требование. Вам нужно будет передать все в закрытии для оценки(). - person Josh C.; 22.04.2013
comment
Кто-нибудь смог запустить два дочерних процесса, выполняющих вызовы phantomjs одновременно? - person Josh C.; 22.04.2013
comment
@ДжошС. Не понимаю, как оценить этот дочерний процесс. Можете ли вы пролить немного больше света? - person morgs32; 09.12.2013

С v2 of phantomjs-node довольно легко распечатать HTML после его обработки.

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

Это покажет вывод, как он был бы отображен в браузере.

Изменить 2019:

Вы можете использовать async/await:

const phantom = require('phantom');

(async function() {
  const instance = await phantom.create();
  const page = await instance.createPage();
  await page.on('onResourceRequested', function(requestData) {
    console.info('Requesting', requestData.url);
  });

  const status = await page.open('https://stackoverflow.com/');
  const content = await page.property('content');
  console.log(content);

  await instance.exit();
})();

Или, если вы просто хотите проверить, вы можете использовать npx

npx phantom@latest https://stackoverflow.com/
person Amir Raminfar    schedule 15.03.2016
comment
позволяет ли он отображать HTML с учетом строки? - person Yuriy Kravets; 02.05.2017

В прошлом я использовал два разных способа, в том числе метод page.evaluate(), который запрашивает DOM, о котором упоминал Деклан. Другой способ, которым я передал информацию с веб-страницы, - выплюнуть ее оттуда в console.log(), а в сценарии phantomjs использовать:

page.onConsoleMessage = function (msg, line, source) {
  console.log('console [' +source +':' +line +']> ' +msg);
}

Я также мог бы перехватить переменную msg в onConsoleMessage и найти некоторые инкапсулированные данные. Зависит от того, как вы хотите использовать вывод.

Затем в сценарии Nodejs вам нужно будет сканировать вывод сценария Phantomjs:

var yourfunc = function(...params...) {
  var phantom = spawn('phantomjs', [...args]);
  phantom.stdout.setEncoding('utf8');
  phantom.stdout.on('data', function(data) {
    //parse or echo data
    var str_phantom_output = data.toString();
    // The above will get triggered one or more times, so you'll need to
    // add code to parse for whatever info you're expecting from the browser
  });
  phantom.stderr.on('data', function(data) {
    // do something with error data
  });
  phantom.on('exit', function(code) {
    if (code !== 0) {
      // console.log('phantomjs exited with code ' +code);
    } else {
      // clean exit: do something else such as a passed-in callback
    }
  });
}

Надеюсь, это поможет некоторым.

person ultrageek    schedule 31.05.2012

Почему бы просто не использовать это?

var page = require('webpage').create();
page.open("http://example.com", function (status)
{
    if (status !== 'success') 
    {
        console.log('FAIL to load the address');            
    } 
    else 
    {
        console.log('Success in fetching the page');
        console.log(page.content);
    }
    phantom.exit();
});
person yossi    schedule 18.12.2013

Позднее обновление на случай, если кто-то наткнется на этот вопрос:

Проект на GitHub, разработанный моим коллегой, призван помочь вам в этом: https://github.com/vmeurisse/phantomCrawl.

Он все еще немного молод, в нем определенно отсутствует некоторая документация, но приведенный пример должен помочь в выполнении базового сканирования.

person Stilltorik    schedule 26.06.2013

Вот старая версия, в которой я использую работающий узел, экспресс и фантомные файлы, которые сохраняют страницу в формате .png. Вы можете настроить его довольно быстро, чтобы получить html.

https://github.com/wehrhaus/sitescrape.git

person user2950147    schedule 26.04.2014
comment
К вашему сведению, если вы собираетесь использовать ссылку для предоставления ответа, лучше всего включить достаточно информации, чтобы ваш ответ не стал бесполезным, если в какой-то момент в будущем ссылка прервется. - person Rob Watts; 26.04.2014
comment
чтобы сохранить как png, вы просто делаете page.render('file.png') - person Toolkit; 08.02.2017