Как использовать PhantomJS с Node.js

PhantomJS — это автономный сценарий WebKit с мультиплатформой JavaScript API, доступный в таких основных операционных системах, как: Windows, Mac OS X, Linux и другие Unices. Он имеет быструю и встроенную поддержку различных веб-стандартов: обработка DOM, селектор CSS, JSON, Canvas и SVG. PhantomJS полностью отображает страницы под капотом, поэтому результаты можно экспортировать в виде изображений. Это очень легко настроить, и поэтому является полезным подходом для большинства проектов, требующих создания множества скриншотов браузера (если вы ищете, как создавать только скриншоты).

В этой статье вы узнаете, как легко использовать PhantomJS с Node.js с помощью модуля или самостоятельно управлять им с помощью Javascript.

Требования

Вам понадобится PhantomJS (установленный или автономный дистрибутив), доступный из PATH (здесь вы узнаете, как добавить переменную в PATH в окнах). Если он не доступен по пути, вы можете указать исполняемый файл для PhantomJS в конфигурации позже.

Вы можете получить PhantomJS из следующего списка на каждой платформе (Windows, Linux, MacOS и т. Д.) в разделе загрузки официального сайта здесь.

Заметка

на большинстве платформ нет процесса установки, так как вы получите .zip файл с двумя папками, Примеры а также бункер (который содержит исполняемый файл PhantomJS).

Как только вы узнаете, что PhantomJS доступен на вашем компьютере, давайте начнем!

А. Использование модуля

Если вы хотите использовать модуль для работы с PhantomJS в Node.js, вы можете использовать модуль фантома, написанный @ amir20. Этот модуль предлагает интеграцию для PhantomJS в Node.js. Хотя рабочий процесс с Javascript отличается от Javascript, который вы используете для инструктажа PhantomJS, его все же легко понять.

Чтобы установить модуль в свой проект, выполните в терминале следующую команду:

npm install phantom --save

После завершения установки модуля вы сможете получить доступ к модулю, используя require("phantom"),

Рабочий процесс (создания страницы, а затем со страницей, выполняет другие действия) остается похожим на сценарии с простым Javascript в PhantomJS. Объект страницы, который возвращается с createPage Метод — это прокси, который отправляет все методы фантому. Большинство вызовов методов должны быть идентичны API PhantomJS. Вы должны помнить, что каждый метод возвращает Promise.

Следующий скрипт откроет веб-сайт Stack Overflow и напечатает HTML-код домашней страницы в консоли:

var phantom = require("phantom");
var _ph, _page, _outObj;
phantom.create().then(function(ph){
_ph = ph;
return _ph.createPage();
}).then(function(page){
_page = page;
return _page.open('https://stackoverflow.com/');
}).then(function(status){
console.log(status);
return _page.property('content')
}).then(function(content){
console.log(content);
_page.close();
_ph.exit();
}).catch(function(e){
console.log(e);
});

Если вы используете Node.js v7 +, то вы можете использовать функции асинхронизации и ожидания, которые предлагает эта версия.

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/');
console.log(status);
const content = await page.property('content');
console.log(content);
await instance.exit();
}());

Это значительно упрощает код и намного проще для понимания, чем с Promises.

B. Собственная реализация

Как вы, вероятно, (должны) знать, вы работаете с PhantomJS через файл js с некоторыми инструкциями, затем сценарий выполняется с указанием пути к сценарию в качестве первого аргумента в командной строке (phantomjs /path.to/script-to-execute.js). Чтобы узнать, как вы можете взаимодействовать с PhantomJS с помощью Node.js, создайте следующий тестовый скрипт (phantom-script.js), который отлично работает с PhantomJS. Если вы хотите проверить это, используйте команду phantomjs phantom-script.js в терминале:

/**
* phantom-script.js
*/
"use strict";
// Example using HTTP POST operation in PhantomJS
// This website exists and is for test purposes, dont post sensitive information
var page = require('webpage').create(),
server = 'http://posttestserver.com/post.php?dump',
data = 'universe=expanding&answer=42';
page.open(server, 'post', data, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.content);
}
phantom.exit();
});

Предыдущий код должен просто создать POST-запрос к веб-сайту (очевидно, проверьте, что у вас есть доступ в Интернет во время тестирования).

Теперь мы собираемся использовать Node.js для приведения дочернего процесса, этот скрипт Node должен выполнить следующую команду (ту же, что используется в командной строке):

phantomjs phantom-script.js

Для этого нам понадобится child_process модуль (доступен по умолчанию в Node.js) и сохраните свойство spawn в переменной. child_process.spawn() Метод порождает новый процесс, используя данную команду (в качестве первого аргумента), с аргументами командной строки в аргументах (в качестве второго аргумента). Если опущено, args по умолчанию является пустым массивом.

Объявите переменную child, которая имеет в качестве значения возвращаемое значение из используемого метода spawn. В этом случае первый аргумент для spawn должен быть путь к исполняемому файлу phantomjs (только phantomjs если он находится в пути), а вторым параметром должен быть массив с одним элементом, путь сценария, который должен использовать фантом. Из дочерней переменной добавьте data слушатель для stdout (стандартный вывод) и stderr (стандартный вывод ошибок). Обратный вызов этих слушателей получит массив Uint8Array, который вы, очевидно, не сможете прочитать, если не конвертируете его в строку. Чтобы преобразовать Uint8Array в его строковое представление, мы будем использовать метод Uint8ArrToString (включенный в скрипт ниже). Это очень простой способ сделать это, если вам требуется масштабируемость в вашем проекте.

Создать новый скрипт (executing-phantom.js) со следующим кодом внутри:

/**
* executing-phantom.js
*/
var spawn = require('child_process').spawn;
var args = ["./phantom-script.js"];
// In case you want to customize the process, modify the options object
var options = {};
// If phantom is in the path use 'phantomjs', otherwise provide the path to the phantom phantomExecutable
// e.g for windows:
// var phantomExecutable = 'E:\\Programs\\PhantomJS\\bin\\phantomjs.exe';
var phantomExecutable = 'phantomjs';
/**
* This method converts a Uint8Array to its string representation
*/
function Uint8ArrToString(myUint8Arr){
return String.fromCharCode.apply(null, myUint8Arr);
};
var child = spawn(phantomExecutable, args, options);
// Receive output of the child process
child.stdout.on('data', function(data) {
var textData = Uint8ArrToString(data);
console.log(textData);
});
// Receive error output of the child process
child.stderr.on('data', function(err) {
var textErr = Uint8ArrToString(err);
console.log(textErr);
});
// Triggered when the process closes
child.on('close', function(code) {
console.log('Process closed with status code: ' + code);
});

В качестве последнего шага выполните предыдущий скрипт узла, используя:

node executing-phantom.js

И в консоли вы должны получить следующий вывод:

Time: Thu, 09 Feb 17 06:24:55 -0800
Source ip: xx.xxx.xxx.xxx
Headers (Some may be inserted by server)
REQUEST_URI = /post.php?dump
QUERY_STRING = dump
REQUEST_METHOD = POST
GATEWAY_INTERFACE = CGI/1.1
REMOTE_PORT = 57200
REMOTE_ADDR = 93.210.203.47
HTTP_HOST = posttestserver.com
HTTP_ACCEPT_LANGUAGE = de-DE,en,*
HTTP_ACCEPT_ENCODING = gzip, deflate
HTTP_CONNECTION = close
CONTENT_TYPE = application/x-www-form-urlencoded
CONTENT_LENGTH = 28
HTTP_ORIGIN = null
HTTP_USER_AGENT = Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1
HTTP_ACCEPT = text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
UNIQUE_ID = WJx7t0BaMGUAAHxjI0EAAAAD
REQUEST_TIME_FLOAT = 1486650295.8916
REQUEST_TIME = 1486650295
Post Params:
key: 'universe' value: 'expanding'
key: 'answer' value: '42'
Empty post body.
Upload contains PUT data:
universe=expanding&answer=42

Лично мы предпочитаем, чтобы самореализованный метод работал с PhantomJS, поскольку кривая обучения модуля велика (по крайней мере, для тех, кто знает, как работать с PhantomJS напрямую со скриптами), кроме того, документация не так хороша.

Ссылка на основную публикацию
Adblock
detector