Предыдущий пост -

Phantomjs консольный веббраузер для новичков.

Рубрика: Без категории, Дата: 4 September, 2015, Автор:

Phantomjs – это консольный веб – браузер без экрана headless. Его мы будем использовать для создания ботов и парсеров сайтов с javascript кодом, где данные подгружаются черзе javascript просто спарсить через curl не получиться.

Создание файла который будет загружать JS

Официальный сайт Phantomjs PhantomJS

И так это консольный браузер. Я с гаряча его как бы хотел попробовать на нем писать парсер вместо Curl и WinInet но как то так посмотрел, там все коды нужно делать на JavaScript, поэтому в общем как то не ясно как его оформлять. Короче была идея создать через CreateProcess процесс, создать пайп, перенаправить stdin и stdout и посылать код js на обработку и получать результат. Фиг его знает как он будет работать, да и реализовать это не так просто будет. Наверно все таки WebBrowser лучше будет использовать. Есть еще второй вариант как использовать, это просто запускать JavaScript скрипты и ждать пока они спарсять, но тогда смысл использовать MFC и С++, только ради GUI наверно и возможно как клей. Вообще в этом Phantomjs нужно разбираться, например как он куки сохраняет, а если я выйду из phantomjs и что куки которые были ранее пропадут?

Мне от что то кажется эта штука для написания больших парсер ботов видимо не годится, да можно, но наверняка будет еще менее удобнее чем делать это на WebBrowser. Да честно если подумать то все нужно делать на JavaScript страницу загрузить пиши код на JavaScript, а что на С++? На С++ только процесс создать и запускать с параметром, ну либо попробовать передавать JavaScript в качестве stdin через пайп. Наверно я на ниго забью просто приведем примерчики как он работает да и все.

TimeOut

Показать »

Установкак таймаута, почитать за настройки можно тут Phantomjs .

page.settings.resourceTimeout=5000;

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

1 Выводим Hellow Wordl в Phantomjs

Показать »

console.log('Hello, world!');
phantom.exit();

вывод:

phantomjs test

2 Загрузка страницы через Phantomjs  и сохранение в изображение

Показать »

var page=require('webpage').create();//подключаем модуль webpage
page.open('http://google.ru',function(){//загружаем страницу
    page.render('img.png');//сохраняем в img.png
    phantom.exit();//выходим
});

в результате у нас создастся изображение img.png в котором будет загружена страница google

img

3 Вот код программки которая засекает время загрузки страницы

Показать »

Просто засекаем время загрузки страницы в Phantomjs  вот код:

var page = require('webpage').create(),//подключаем модуль
    system = require('system'),//подключаем модуль system
    t, address;//создаем две переменные

if (system.args.length === 1) {//если аргумент 1, то мы выходим из приложения
    console.log('Exit test.jsn мало аргументов');//вывод сообщения
    phantom.exit();//выход из phantomjs
}

t = Date.now();//засекаем дату в переменную
address = system.args[1];//в ардесс вводим имя переменной урла
console.log(address);//выведем в консоль адресс
page.open(address, function (status) {//запускаем функцию на выполнение
    if (status !== 'success') {//если неудачно загрузилась страница, то ...
        console.log('FAIL to load the address');
    } else {//если удачно то засекаем дату
        t = Date.now() - t;
        console.log('Loading time ' + t + ' msec');//вывод в консоль данные
    }
    phantom.exit();//закрываем phantomjs
});

В консоле мы запускаем браузер и передаем ему наш файл и адрес в качестве параметра, я приведу скрин консоли из webshtorm IDE

webshtorm consoleкак видно загрузило страницу за 10583 мсек, то есть за 10 секунд получается 🙂 .

4 Пример кода, который парсит все ссылки на странице и сохраняет и выводит их в консоль

Показать »

код хорошо закомментирован, поэтому без пояснений 🙂

var sys = require('system');//подключаем модуль system
var page = require('webpage').create();//подключаем модуль webpage
var siteUrl = 'http://kselax.ru/';//урл куда откуда парсим

function exit(code) {//функция для выхода
    setTimeout(function() {
        phantom.exit(code);
    }, 0);
    phantom.onError = function(){};
}

page.open(siteUrl, function(status) {
    // Данный статус указывает, что ссылка открылась
    // успешно и вернулся ответ сервера с кодом 200
    if (status === 'success') {
        //подключаем jQuery
        page.injectJs('/js/jquery.js');//подключаем JQuery
        // Выполняем весь CSS, JS код на странице
        var Links = page.evaluate(function() {
            var links = $('html').find('a');//ищем все линки
            var hrefs = [];//создаем переменную массив

            $.each(links, function(num, item) {//num наверно индекс, а item походу элемент
                var href = $(item).attr('href');
                if (href !== '#') {//если не решетка то добавляем в массив
                    hrefs.push(href);//вставляем в массив
                }
            });

            return hrefs;//возвращаем массив, он запишется в
            //переменную Links
        });

        // Вывод результата через обычный console.log
        console.log(JSON.stringify(Links));
    }

    // Закрываем PhantomJS
    exit();
});


в консоли получаем результат

webshtorm res

Получить в программе аргументы командной строки (модуль system)

Показать »

Почитать за него можно тут Phantomjs .

И вот код

//Подключаем system module чтобы можно получить
//из командной строки значения аргументы
var system =require('system');

var url=system.args[1];
var img=system.args[2];

console.log("url="+url+" img="+img+"n");

phantom.exit(1);//выходим из phantomjs

и на экран получаем

phantomjs

Работа с файлами (модуль fs)

Показать »

почитать за него можно тут Phantomjs . А от пример кода который создает файл.

var fs=require('fs');

var text ="hellow world";
var file="output.txt";
fs.write(file,text,"w");//запись в файл
phantom.exit();

Парсим массив ссылок

Показать »

Первый способ это обход через switch

var webpage=require('webpage');

var url=[];
url[0]="http://google.ru";
url[1]="http://microsoft.com";
url[2]="http://kselax.ru";
url[3]="http://cyberforum.ru";
url[4]="http://fl.ru";
url[5]="http://podrobnosti.ua";

var step=1;
var time=500;
var intervalId=setInterval(tick,time);
var i=0;
function tick(){
    switch(step){
        case 1:{
            clearInterval(intervalId);//останавливаем счетчик
            step=2;
            console.log(url[i]);
            var page=webpage.create();
            page.settings.resourceTimeout=15000;//время ожидания 15 секунд
            page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0';
            page.open(url[i],function(status){
                if(status==="success"){
                    console.log("success"+i);
                    page.render("img"+i+".png");
                    page.close();
                    i++;
                    if(i<url.length) {step=1;}
                    else step=3;
                }
                else{
                    page.close();
                    console.log("not success"+i);
                    i++;
                    if(i<url.length) {step = 1;}
                    else step=3;
                }
            });
            intervalId=setInterval(tick,time);
            break;
        }
        case 2:{
            console.log("TICK"+step);
            break;
        }
        case 3:{
            clearInterval(intervalId);
            phantom.exit();
        }
    }
}

Второй способ это как бы рекурсивная типо функция

var webpage=require("webpage");

var url=[];
url[0]="http://google.ru";
url[1]="http://microsoft.com";
url[2]="http://kselax.ru";
url[3]="http://cyberforum.ru";
url[4]="http://fl.ru";
url[5]="http://podrobnosti.ua";

var i=0;
pars();

function pars(){
    var page=webpage.create();
    page.settings.resourceTimeout=10000;
    page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0';
    page.open(url[i],function(status){
        if(status=="success"){
            console.log("success"+i)
            page.render("img"+i+".png");
            page.close();
            if(++i<url.length){pars();}
            else{phantom.exit();}
        }
        else{
            console.log("not success"+i)
            page.close();
            if(++i<url.length){pars();}
            else{phantom.exit();}
        }
    });
};

Авторизация с помощью Phantomjs на сайте fl.ru

Показать »

у вас появится 3 изображения которые будут показывать этапы, авторизация реально проходит.

var webpage=require('webpage');
var fs=require('fs');
var system=require('system');

var page=webpage.create();
var url="http://fl.ru";

var login,pass;
console.log("Enter login");
login=system.stdin.readLine().trim();
console.log('Enter password');
pass=system.stdin.readLine().trim();
console.log("login="+login+" pass="+pass);

page.open(url,function(status){
    if(status==="success"){
        console.log("success");
        page.render('img.png');
        fs.write('index.html',page.content,'w');
        //заполняем
        page.evaluate(function(login,pass){
            var e1 = document.querySelector('input[name="login"]');
            e1.value=login;
            var e2=document.querySelector('input[type="password"]');
            e2.value=pass;
            var e3=document.querySelector('input[type="submit"]');
            e3.click();
        },login,pass);

        page.render("img1.png");


        setTimeout(function(){
            page.render("img2.png");
            phantom.exit();
        },3000);

    }
    else{
        console.log("not success");
        phantom.exit();
    }
});

Делаем скрин изображения загруженного изображения. Cпособ просто загружаем ссылку и делаем скрин изображения, но оно получается маленьким.

Этот способ работает когда мы задаем большой размер ширины и высоты например такой
page.viewportSize={width: 2000, height: 2000};//задаем размер браузера

Показать »

var webpage=require('webpage');

var url='http://www.kselax.ru/wp-content/uploads/2015/09/Proxy-Switcher.png';

var page=webpage.create();
page.viewportSize={width: 2000, height: 2000};//задаем размер браузера
page.open(url,function(status){
    if(status==="success"){
        console.log('success');
        console.log(page.content);
        page.render("img.png");
        //выполняем JS и получаем размеры изображения
        var rect = page.evaluate(function() {
            var e = document.querySelector('img');
            if(e != null)
                return e.getBoundingClientRect();//возвращает размер изображения
            return "";
        });
        if(rect!==""){
            old = page.clipRect;//запоминаем старый
            page.clipRect = rect;//присваиваем новую
            page.render("img.png", {format: 'png', quality: '100'});//сохраняем картинку
            page.clipRect = old;//восстанавливаем старый
        }
        phantom.exit();
    }
    else{
        console.log('not success');
        phantom.exit();
    }
});

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

как оказалось этот способ работает когда мы задаем по нулям
page.viewportSize={width: 0, height: 0};//задаем размер браузера

Показать »

var webPage = require('webpage');
var page = webPage.create();
var url='http://www.kselax.ru/wp-content/uploads/2015/09/Proxy-Switcher.png';

var expectedContent = '<html><body style="margin: 0px;"><img src="'+url+'"></body></html>';
page.viewportSize={width: 0, height: 0};//задаем размер браузера
page.frameContent=expectedContent;// подгружает контент
var rect=page.evaluate(function(){
    var e=document.querySelector('img');
    if(e!=null)
        return e.getBoundingClientRect();
    return "";
});


setInterval(function(){
    if(rect!=="") {
        var old = page.clipRect;
        page.clipRect=rect;
        page.render("img.png",{format:'png',quality:'100'});
        page.clipRect=old;
    }
    page.render('img1.png');
    phantom.exit();
},3000)

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

Показать »

var webpage=require('webpage');
var system=require('system');

var url=system.args[1];//урл страницы

console.log("url="+url);
var page=webpage.create();

var step=1;
var time=500;
intervalID=setInterval(tick,time);

var links;//массив ссылок на изображения
var count=0;

function tick(){
    switch(step){
        //читаем страницу
        case 1:{
            clearInterval(intervalID);
            console.log("TICK"+step);
            page.open(url,function(status){
                if(status==="success"){
                    console.log("success");
                    //нужно получить все ссылки на изображения
                    links=page.evaluate(function(str) {
                        var hrefs=[];
                        var mass= document.querySelectorAll('img');
                        for(var i=0;i<mass.length;i++)
                            hrefs[i]=mass[i].src;
                        return hrefs;



                    });
                    console.log("links.length="+links.length);

                    for(var i=0;i<links.length;i++){
                        console.log(i+" = "+links[i]);//не выводится
                    }

                    step=4;
                }
                else{
                    console.log("not success");
                    step=3;
                }
            });
            step=2;
            intervalID=setInterval(tick,time);
            break;
        }
        //просто убиваем время
        case 2:{
            console.log("TICK"+step);
            break;
        }
        //выход из программы
        case 3:{
            phantom.exit();
        }
        case 4:{//копируем изображения
            console.log('TICK'+step);
            clearInterval(intervalID);
            console.log(count);
            page=webpage.create();
            page.viewportSize = {width: 2000, height: 2000};//задаем размер
            page.open(links[count++],function(status){
                if(status==="success"){
                    console.log("success");
                    var rect=page.evaluate(function(){
                        var e=document.querySelector('img');
                        if(e!=null)
                            return e.getBoundingClientRect();
                        return "";
                    });
                    setTimeout(function(){
                        if(rect!=""){
                            var old=page.clipRect;
                            page.clipRect=rect;
                            page.render('img'+count+'.png');
                        }

                        if(count<links.length){step=4;}
                        else step=3;//выходим из программы
                    },1000);
                }
                else{
                    console.log("not success");
                    if(count<links.length){step=4;}
                    else step=3;//выходим из программы
                }
            });

            step=2;
            intervalID=setInterval(tick,time);
        }
    }//конец switch
};

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

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

Показать »

var webpage=require('webpage');
var system=require('system');

var url=system.args[1];//урл страницы

console.log("url="+url);
var page=webpage.create();

var step=1;
var time=500;
intervalID=setInterval(tick,time);

var links;//массив ссылок на изображения
var count=0;

function tick(){
    switch(step){
        //читаем страницу
        case 1:{
            clearInterval(intervalID);
            console.log("TICK"+step);
            page.open(url,function(status){
                if(status==="success"){
                    console.log("success");
                    //нужно получить все ссылки на изображения
                    var str=page.content;
                    var regexp=/<img[^<>]*?src[^<>]*?=[^<>]*?"([^<>]*?)"[^<>]*?>/g;
                    var r;
                    console.log("tyt");
                    links=[];
                    for(var i=0;r=regexp.exec(str);i++){
                        console.log("i="+i+" "+r[1]);
                        links[i]=r[1];
                    }

                    step=4;
                }
                else{
                    console.log("not success");
                    step=3;
                }
            });
            step=2;
            intervalID=setInterval(tick,time);
            break;
        }
        //просто убиваем время
        case 2:{
            console.log("TICK"+step);
            break;
        }
        //выход из программы
        case 3:{
            phantom.exit();
        }
        case 4:{//копируем изображения
            console.log('TICK'+step);
            clearInterval(intervalID);
            console.log(count);
            page=webpage.create();
            page.viewportSize = {width: 0, height: 0};//задаем размер
            var frameContent = '<html><body style="margin: 0px;"><img src="'+links[count++]+'"></body></html>';
            page.viewportSize={width: 0, height: 0};//задаем размер браузера
            page.frameContent=frameContent;// подгружает контент

            setTimeout(function(){

                var rect=page.evaluate(function(){
                    var e=document.querySelector('img');
                    if(e!=null)
                        return e.getBoundingClientRect();
                    return "";
                });

                setTimeout(function(){
                    if(rect!==""){
                        var old=page.clipRect;
                        page.clipRect=rect;
                        page.render('img'+count+'.png',{format: 'png',quality: '100'});
                        page.clipRect=old;
                        if(count<links.length){step=4}
                        else step=3;//выход из программы
                    }
                    else{
                        if(count<links.length){step=4}
                        else step=3;//выход из программы
                    }
                },1000);
            },2000);



            step=2;
            intervalID=setInterval(tick,time);
        }
    }//конец switch
};

Меняем прокси

Показать »

phantomjs.exe --proxy=ip:port script.js

 

Простой примерчик

var page = require('webpage').create();//создаем типо страницу
page.viewportSize = {width: 1024, height: 1500};//задаем размер

//загружаем
page.open('http://google.ru', function(status) {
  console.log("Status: " + status);
  if(status === "success") {
    page.render('example1.png');
  }
  phantom.exit();
});

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Комментарии:

  • Alex

    Хороший по виду материал, по функционалу еще не тестил. Видел, что другие пробовали и не ругались – значит скрипты рабочие.
    На русском очень мало материала по phantomjs и начинающему очень трудно.
    Хотел бы с автором обсудить одну тему по phantomjs (типа заказать скрипты): если он прочитает этот пост, просьба отписать свои координаты – мыло.
    Автору Респект!

    • admin_kselax

      Да на нем раньше можно было ботов делать, или веббраузер использовать, а щас новая капча от гугла вышла где проверяется я не робат и прочее, если такая капча стоить то бота не сделаешь.
      А так да страницы с Javascript кодом хорошо парсить, все загрузилось скопировал.
      mail: neovich@mail.ua я редко письма проверяю.

  • Олег

    Здравствуйте.
    Есть парсер, написан с использованием phantomjs 2.1.1 и вроде как оно и работает только как то много страниц пропускает, не возвращает контент,
    часто встречается такое page.evaluate undefined method. Ссылки в фантом передаются по одной.

    • admin_kselax

      В этой evalute выполняется наш собственный javascript code , типо как мы к странице подключаемся и выбираем что то (как в гугл консоли например) . Наверно в этой evalute прописан javascript код и он что то ищет на странице и возвращает undefined. Не знаю что сказать. PhantomJs хорошо парсит сайты где есть javascript код и подгрузка идет данных через js, CURL – лом такие сайты не попарсишь.

      На phantomJs по другому щас парсю, если бывает нужно, Делаем скрипт который просто скачивает страницу и сохраняет например в файл data.html , а потом этот файл читаем из php и тянем что нам нужно. Вызов phantomjs идет из php туда передаю этот скрипт на javascript и url как параметр . И все.

      Щас парсеры давно не делал, за них никто не хочет платить, разве что для себя что то спарсить какую то базу с сайта и себе залить или еще что то …. 🙂


Оставить комментарий

Your email address will not be published. Required fields are marked *