PhantomJS – это возможность работать с WebKit из консоли используя JavaScript и без браузера. Для чего это нужно? Основное предназначение — парсить сайты, заполучив весь сгенерированный HTML — код, даже если DOM — дерево генерируют запросы и ответы AJAX или просто отскринить сайт целиком. Как правило, PHP не позволяет парсить динамически загружаемые страницы и отличным решением является метод, когда мы получаем сгенерированный DOM HTML страницы, сохранив в какой-то директории и далее вскармливаем его статическому PHP -парсеру.
CasperJS – вспомогательный инструмент написанный на JavaScript как обертка PhantomJS. На официальном сайте перечислены следующие основные возможности:
- определение и порядок итераций браузера
- заполнение и отправка форм
- клик и переход по ссылкам
- создание скриншотов страницы и ее части
- удаленное тестирование DOM
- логирование событий
- загрузка ресурсов и подключение библиотек
- написание функциональных тестов и сохранение в формате JUnit XML
- Допиливание веб контента
CasperJS облегчает использование сложного и голого API PhantomJS, поэтому он и называется вспомогательным инструментом, который облегчает использование PhantomJS. Оба они устанавливаются в систему и вызываются из командной строки, через которую передаются параметры для ввода и вывода значений и результата, но мы можем вызывать их и из PHP через команды в функции exec(…), после чего можем отскринить, сохранять или статически допарсить полученный результат через инструменты PHP.
Установка PhantomJS
cd /usr/local/share sudo wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 sudo tar -xvf phantomjs-2.1.1-linux-x86_64.tar.bz2 sudo mv phantomjs-2.1.1-linux-x86_64 phantomjs-2.1.1 sudo ln -s /usr/local/share/phantomjs-2.1.1/ /usr/local/share/phantomjs sudo ln -s /usr/local/share/phantomjs/bin/phantomjs /usr/local/bin/phantomjs
На момент написания статьи, а это дата 03.09.2017 актуальной версией была 2.1.1, поэтому, в последующем ссылки и версии могут меняться, проверить их можно на официальном сайте на странице загрузок PhantomJS.
Чтобы убедиться, что у нас все нормально установилось необходимо выполнить команду показа версии PhantomJS
phantomjs --version
И если установка прошла удачно, то эта команда вернет версии без каких-либо «варнингов» и «эрроров»
Установка CasperJS
CasperJS устанавливаем схожим образом, даже чуть полегче, если указать ссылку на GitHub
cd /usr/local/share sudo git clone -b master git://github.com/n1k0/casperjs.git cd casperjs sudo ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs
Чтобы убедиться, что у нас все отлично установилось выполним команду вывода версии
casperjs --version
Выполняем операции CasperJS из PHP
Как уже писали, для выполнения команд PhantomJS нам нужно из PHP выполнять команды на системном уровне и для этого у нас есть специальная функция exec(…). Так как весь код PhantomJS через обертку CasperJS пишется на языке JavaScript, то полезно разделить логику работы, поделив задачи в отдельных файлах, поэтому создадим отдельный файл casper-script.js для написания кода запросов на JS и в итоге код на PHP для передачи и выполнения команд будет следующим
exec('casperjs /home/UserName/web/my.site.com/public_html/parser/js/casper-script.js https://www.google.ru/', $output, $return_var);); print_r($output); print_r($return_var);
В первом параметре передаем строку с командами для OS в котором через пробелы указываем первым сервис, вторым — скрипт на JavaScript для описания того, что должен PhantomJS делать через обертку CasperJS, третьим — URL адрес сайта или ресурса, над которым мы хотим совершать операции. Данная строка не фиксированна, поэтому, количество параметров строки может меняться. Далее у нас идут второй и третий параметры функции exec(…) для вывода результата выполнения.
Как видно выше путь к файлу casper-script.js указан абсолютным. По умолчанию, файлы, скриншоты после опрации будут сохранятся в текущей директории, где выполняется команда exec(). Для начала выполним обычную операцию и напишем в файле casper-script.js следующий код
var casper = require("casper").create(); casper.echo("Casper CLI passed args:"); require("utils").dump(casper.cli.args); casper.echo("Casper CLI passed options:"); require("utils").dump(casper.cli.options); casper.exit();
Пример получения скриншота сайта на CasperJS/PhantomJS
Данный код демонстрирует получение скриншота сайта по его URL и сохранение в текущей директории
exec('casperjs /home/UserName/web/my.site.com/public_html/parser/js/casper-script.js 2>&1', $output, $return_var); print_r($output); print_r($return_var);
var casper = require('casper').create({ verbose: true, logLevel: 'debug', pageSettings: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36' } }); casper.options.viewportSize = {width: 1280, height: 1024}; casper.start("http://stackoverflow.com/questions/tagged/phantomjs"); casper.then(function() { casper.capture("stackoverflow.png"); }); casper.run();
После выполнения скриншот будет сохранен под названием stackoverflow.png
Пример получения сгенерированного динамически DOM HTML — документа через CasperJS/PhantomJS
exec('casperjs /home/UserName/web/my.site.com/public_html/parser/js/casper-script.js https://google.com html.txt --ssl-protocol=TLSv1', $output, $return_var);
var casper = require('casper').create(); casper.userAgent('Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19'); var url = casper.cli.args[0]; var outputPath = casper.cli.args[1]; casper.start(url); casper.then(function() { casper.wait(5000, function() { // Get HTML var html = this.evaluate(function(){ return document.querySelector("html").outerHTML; }); // Save HTML fs = require('fs'); fs.write(outputPath, html, 'w'); }); }); casper.run();
В данном примере получим первый аргумент из командной строки в виде URL, который надо заполучить и второй аргумент — путь и имя файла, в котором будет сгенерированный DOM HTML.