Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   как с помощью phantomjs пройти по ссылкам (https://javascript.ru/forum/misc/58331-kak-s-pomoshhyu-phantomjs-projjti-po-ssylkam.html)

ninja2 16.09.2015 08:31

как с помощью phantomjs пройти по ссылкам
 
Как с помощью phantomjs обойти массив ссылко, от код и не работает???
var webpage=require('webpage');

var url=[];
url[0]="http://google.ru";
url[1]="http://microsoft.com";

var page=webpage.create();

for(var i=0;i<url.length;i++)
{
    console.log(url[i]);
    page.open(url[i],function(status){
        if(status==="success"){
            console.log("success"+i);
            page.render("img"+i+".png");
        }else
        {
            console.log("not success"+i);
        }
    });
}

//phantom.exit();

ninja2 16.09.2015 08:55

Так что никто не знает как делать? Я знаю можно черзе таймер и switch, но мне хочется через цикл по простому сделать. Как сделать так чтобы цикл ожидал завершения работы функции page.open, а затем только шел дальше?????

ninja2 16.09.2015 09:16

Так что через таймеры делать? Похоже вариантов нету. Или можно как то сделать чтобы функция open не возвращала управление сразу, а только после выполнения????

Skipp 16.09.2015 09:43

Суть событийного программирования, состоит в построении цепочек из callback функций.

На вскидку:

url[0]="http://google.ru";
url[1]="http://microsoft.com";

i = 0;
function parse(i) {

    page.open(url[i], function() {
        ...
        ...
        ...
        i++
        if(url[i]) parse(i);
    });

}


Конечно можно и покрасивее это сделать.

ninja2 16.09.2015 11:31

Цитата:

Сообщение от Skipp (Сообщение 388807)

Конечно можно и покрасивее это сделать.

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

caetus 16.09.2015 11:33

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


https://learn.javascript.ru/recursion

ninja2 16.09.2015 11:35

вообе кумарит это phantom, похоже нужно еще и задержку делать после выхода из функции open, если не делать задержку то оно с ошибками парсит или я что то не то делаю хз.

ninja2 16.09.2015 11:45

Цитата:

Сообщение от caetus (Сообщение 388817)
Максимальная глубина рекурсии в браузерах ограничена, точно можно рассчитывать на 10000 вложенных вызовов, но некоторые интерпретаторы допускают и больше.


https://learn.javascript.ru/recursion

А Phantomjs это типо браузер, а сколько памяти можно использовать, от например я 1000 ссылок функции передам и она должна вернуть массив из 1000 элементов с спарсеным текстом.

ninja2 16.09.2015 11:53

Вот код написал
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 page=webpage.create();

//устанавливаем 10 секунд ожидания запроса
page.settings.onResourceTimeout=500;

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]);
            page.settings.resourceTimeout=15000;//время ожидания 15 секунд
            page.open(url[i],function(status){
                if(status==="success"){
                    console.log("success"+i);
                    page.render("img"+i+".png");
                    i++;
                    if(i<url.length) {
                    //    clearInterval(intervalId);
                    //    intervalId=setInterval(tick,time);
                        step=1;
                    }
                    else step=3;
                }
                else{
                    console.log("not success"+i);
                    i++;
                    if(i<url.length) {
                    //    clearInterval(intervalId);
                    //    intervalId=setInterval(tick,time);
                        step = 1;
                    }
                    else step=3;
                }
            });
            intervalId=setInterval(tick,time);
            break;
        }
        case 2:{
            console.log("TICK"+step);
            break;
        }
        case 3:{
            clearInterval(intervalId);
            phantom.exit();
        }
    }
}


Он у меня два раза копирует одни и теже изображения, а когда раскоменнтирую строки переустановки счетчика тогда нормально. Че так? Че он неуспевает обнулятся или че за нафиг?

На нем большие парсера можно написать или нет?, Это ужас постоянно таймеры запускать :(

Щас и с задержкой половина урлов не спарсило, мб. большую нужно поставить, 500 вроде мало, когда ставил 1000 то норм было.
Как он работает не ясно.... Через раз парсит, раз норм все урлы, а другой раз пару урлов.

ninja2 16.09.2015 12:36

от так сделал тоже через раз копирует изображения и бывают одинаковые. хз. че оно так лагает
var webpage=require("webpage");

var page=webpage.create();

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(){
    page.settings.resourceTimeout=10000;
    page.open(url[i],function(status){
        if(status=="success"){
            console.log("success"+i)
            page.render("img"+i+".png");
            if(++i<url.length){pars();}
            else{phantom.exit();}
        }
        else{
            console.log("not success"+i)
            if(++i<url.length){pars();}
            else{phantom.exit();}
        }
    });
};


Мб. что то в коде не так, нужно мб. как то phantomjs останавливать или что то делать????

newtimebigtime 16.09.2015 12:46

Цитата:

Сообщение от caetus
Максимальная глубина рекурсии в браузерах ограничена, точно можно рассчитывать на 10000 вложенных вызовов, но некоторые интерпретаторы допускают и больше.

Вроде это касается только синхронных вызовов. В случае ТС'а не должно быть ограничений. Там стек не выстраивается. Коллбеки просто кидаются в очередь.

newtimebigtime 16.09.2015 12:59

i=0

tst=function(){i++; try{tst()}catch(e){console.log(i)}}

tst()

i=0

tst=function(){if(i===30000) return console.log(i); i++; setTimeout(function(){tst()})}

tst()

/*
результат для ноды:
11434
30000
*/

скорей всего для асинхронных вызовов нет ограничений. Но они медленней.

UPD хотя на хроме этот код не отрабатывает почему-то, вывода в консоль нет. В ФФ -- ок

caetus 16.09.2015 13:27

хром 40к без Timeout стек переполнен !

function f (i) {


console.log(1)
	if(i > 0) setTimeout(function () {f(i-1)}, 0);
	else console.log(i)
}

f(40000)

ninja2 16.09.2015 13:44

а как вообще парсера пишутся на phantomjs???? Мб. просто маленькие скрипты посоздавать которые будут по одному урлу считывать, а затем создавать процесс и вызывать консоль со скриптом???
А если так сделать, то куки пропадут да?
Массив из 5 ссылок нормально спарсить не могу даже.

caetus 16.09.2015 13:48

можно пошаманить и обойти стек :)
function f (i, t) {

if(t == 10000) {
  setTimeout(function () { 
    console.log(i)
    f(i, 0)
  }, 0);
}
		
else if(i) f(i-1, t+1);


}
var a = 100000;
f(a, 0)

caetus 16.09.2015 13:49

объясни что тебе нужно сделать и я постараюсь помочь )

http://habrahabr.ru/post/224081/

ninja2 16.09.2015 14:07

Цитата:

Сообщение от caetus (Сообщение 388848)
объясни что тебе нужно сделать и я постараюсь помочь )

http://habrahabr.ru/post/224081/

неправильно работал скрипт что выше с рекурсией. нужно было каждый раз вызывать var page=webpage.create() и закрывать, тогда без ошибок, вот так
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();}
        }
    });
};

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

Вот с помощью 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();
        }
    }
}


А от большие парсера походу не сильно удобно будет писать??? Наверно лучше делать с помощью switch чем на функции разбивать. А мб. еще есть какой то лучший способ?????

Еще интересно как phantom куки сохраняет, от если я сделаю авторизацию через phantom , потом его закрой и заново открою то я буду авторизован или нет??? Нада проверить. И изображения не ясно как их копировать. От есть урл на изображение http://hsto.org/files/59f/f05/718/59...e54ea5e2b3.png и как его скопировать через phantom? просто загрузить и сохранить? Щас проверю.

Хочу попробовать большой парсер написать типо товары напарсить для интернет магазина, я такой на curl писал, а тут не ясно как делать.
И как прокси поменять не ясно :)

ninja2 16.09.2015 14:41

никак изображение нимогу сохранитЬ, есть изображение http://hsto.org/files/59f/f05/718/59...e54ea5e2b3.png, загружаю его в браузер и дальше что?
вот код, загружаю страницу и сразу ошибка вылазит
var webpage=require('webpage');
//var fs=require('fs');

var url="http://hsto.org/files/59f/f05/718/59ff0571875a45e79162ebe54ea5e2b3.png";
var page=webpage.create();

page.open(url,function(status){
    if(status==="success"){
    //    page.render("img.png");
    //    console.log(page.content);
    //    fs.write("img1.png",page.content,"w");
        phantom.exit();
    }
    else{
        phantom.exit();
    }
});

Ошибка:
E:\project_web\porject2>phantomjs test5.js
PhantomJS has crashed. Please read the crash reporting guide at
<http://phantomjs.org/crash-reporting.html> and file a bug report at
<https://github.com/ariya/phantomjs/issues/new>.
Please attach the crash dump file:
C:\TEMP\28edde00-9364-4e54-ae01-4cb6df7a9cc8.dmp


Если раскоментировать строки, то в img.png изображение но маленькое, а в img1.png испорченое изображение. Нужно как то загрузить, а как хз.

Мб. как то можно изображение загрузить по ссылке с помощью просто javaScript без phantomjs????

ninja2 16.09.2015 15:02

Так что никто не знает как сохранить изображение спомощью javaScript???? Есть ссылка на img, нужно как то его сохранить, все ж просто :)

Skipp 16.09.2015 16:19

ninja2,
Это не рекурсия, разница в том, что функция выполняется асинхронно.

Про сохранение изображений, глянь там есть папка examples, в ней есть похожие примеры.

ninja2 16.09.2015 17:09

Там есть пример от тут, но он не работает пишет ошибку:
E:\project_web\porject2>phantomjs test5.js http://ariya.github.io/svg/tiger.svg tiger.png
PhantomJS has crashed. Please read the crash reporting guide at
<http://phantomjs.org/crash-reporting.html> and file a bug report at
<https://github.com/ariya/phantomjs/issues/new>.
Please attach the crash dump file:
C:\TEMP\58579f65-f122-4a02-9952-41983592337a.dmp

пример с тигром.
Заработал с тигром, копирует, только другие копирует и добавляет лишний нивидимый размер
[IMG SRC=http://f3.s.qip.ru/pQ6zADwr.png]

ninja2 16.09.2015 17:50

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

Да что то я гуглю и ниче нету. Че JavaScript не может сохранить изображение из интернета? Я JavaScript плохо знаю, просто интересно :) .

ninja2 16.09.2015 20:45

Ладно изображение мы не сохраним, это бесполезно, можно ссылку выводить на изображение в консоль, а из консоли считывать, фиг с ним с этим изображением.

Тут еще такие дела я сделал авторизацию на сайт fl.ru и второй раз на него захожу в phantomjs определяет что я не авторизован. Почему coocies не сохранились как в нормальном браузере???? Мне что каждый раз делать авторизацию? Ну это ужас, похоже phantomjs нужно только запускать как процесс, просто как самостоятельное приложение оно наврятли нормально работать будет. парсер так фиг нормальный напишешь или нет????

На чем вообще парсеры пишут??? Хотелось бы чтобы все было на JavaScript, а за кодировку еще забыл. Нужно ж еще и кодировку определять и если что перекодировать, в JavaScript такое есть или нет? Вообще что то javaScript убоговатый чуток :)

ninja2 16.09.2015 22:52

Не лучше всетаки сохранить и изображение и все сделать через JS. Парсера быстро пишутся на нем, неохота смешивать, хочется все на js сделать :)

ninja2 18.09.2015 08:30

А почему у меня не выводятся остальные элементы после первого которые я получаю с помощью getElementsByTagName ???
var links=page.evaluate(function() {
                    return document.getElementsByTagName('img');
                    });
                    console.log("links.length="+links.length);

                    console.log(links[0].src);//выводится нормально
                    console.log(links[1].src);//этот уже не выводится
                    for(var i=0;i<links.length;i++)
                    {
                        console.log(i);
                        console.log(links[1].src);//не выводится
                    }

1 элемент выводится и зависает на console.log(links[1].src); в чем проблема????
Выводит что 10 элементов в массиве, а получаю только один, остальные виснут. Как получить все src????

Разобрался, вывел просто console.log(links[i]); и оказалось что в 0 есть [object] а в остальных null, и что делать, почему функция вернула null и 9 элементов?
Как получить все изображения на странице???

querySelectorAll тоже также в первом элементе есть объект, а в 9 нету

От такой код работает, когда его в конец страницы добавляю
<script>
    var mass= document.querySelectorAll('img');
    alert(mass.length);
    for(var i=0;i<mass.length;i++) {
        alert(mass[i].src);
    }
</script>

и вообще length тут 12, а у меня 10, че то evaluate не правильно как то работает.

через JQuery получилось получить 10 изображений, через функции jS ниче не работает :(

Короче ясно, нужно и массив в функции evaluate обходить, тогда все нормально. Наверно JavaScript функции и работать не будут вне evaluate. Какаето фигня.

mrbanan 19.09.2015 13:47

У меня так же самая проблема. Если парсю маленькие тестовые странички - всё нормально, как только большие страницы, сразу какая-то фигня, штуки 2 обработает и останавливается.
Запускаю через консоль, кто знает что и от чего это когда в консоли не решётка появляется типа user@server# а курсор мигает вот так

Видите на скрине после for is end он ждёт чего-то, что бы дать команду приходится Ctrl+C нажимать и тогда уже консоль опять реагирует.

Ещё не очень понятно phantom.exit где ставить правильно. Вот скрипт.
var urls = [
"https://site.ru/page=1",
"https://site.ru/page=2",
"https://site.ru/page=3",
"https://site.ru/page=4"
];
var numurls = urls.length;

for (u = 0; u < numurls; u++) {

    var fs = require('fs');
    var webPage = require('webpage');
    var page = webPage.create();
    
    console.log('link '+ urls[u]);
    page.open(urls[u], function(status) {
      console.log('Status: ' + status);
      if (status === 'success') {
        
        //моя обработка и запись
        
        console.log('for is end');

        //phantom.exit();
      }
    });
    
} // конец цикла 1 url

mrbanan 19.09.2015 13:52

Ах да ninja2, забейте на картинки, спарсите их потом на php, у меня уже есть готовый парсер, работает отлично, скорость парсинга офигенная 45 картинок за 0,3 секунды.
Phantom применять что бы картинки парсить это как-то странно короче, он для более сложных задач обычно применяется.

ninja2 20.09.2015 02:19

Цитата:

Сообщение от mrbanan (Сообщение 389222)
Ах да ninja2, забейте на картинки, спарсите их потом на php, у меня уже есть готовый парсер, работает отлично, скорость парсинга офигенная 45 картинок за 0,3 секунды.
Phantom применять что бы картинки парсить это как-то странно короче, он для более сложных задач обычно применяется.

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

Та уже разобрался как картинки парсить, от тут в самом низу несколько примеров, есть пример авторизации на fl.ru

у тебя код может зависать потому что функции phantom.exit(); нету или бывает у меня зависало когда ошибка была в коде где то ошибка.

А как через php парсить, это типо сохранить в файл ссылки и потом скопировать или как то можно из php процессы создавать? От интересно можно через php запустить консольное приложение с параметрами???

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

mrbanan 20.09.2015 08:02

Сам пока не успел опробовать но из php как-то так:
shell_exec('/usr/local/bin/phantomjs -v');

С параметром
$title = shell_exec('/usr/local/bin/phantomjs /script.js http://market.yandex.ru/model.xml?modelid=8230052&hid=90594');

А вы подскажите мне как поймать этот передаваемый параметр в ЯваСкрипте?

ninja2 20.09.2015 10:17

Цитата:

Сообщение от mrbanan (Сообщение 389312)
$title = shell_exec('/usr/local/bin/phantomjs /script.js http://market.yandex.ru/model.xml?modelid=8230052&hid=90594');

А вы подскажите мне как поймать этот передаваемый параметр в ЯваСкрипте?

var system=require('system');
var url=system.args[1];
console.log(url);
phantom.exit();

вроде так.

protey2004 22.03.2016 05:20

По мне, так парсеры прекрасно пишутся в связке с php.
Я phantomjs использую для исполнения js кода на страницах, которые что-то генерирую динамически. Получается вполне универсальная вещь, которая и картинки умеет загружать и любую информацию доставать, даже под авторизацией.

Пример вызова из php:
echo shell_exec('/usr/bin/phantomjs /phantom.js http://market.yandex.ru/model.xml?modelid=8230052&hid=90594'');


Пример phantom.js:
"use strict";
var page = require('webpage').create(),
system = require('system'),
	url = system.args[1];

page.open(url, function(status) {
    if (status === "success") {
        page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
            page.evaluate(function() {
                console.log($('h1').html());
            });
            phantom.exit(0);
        });
    } else {
      phantom.exit(1);
    }
});


Далее, php часть можно вставлять в любое место php парсера и тем же phpQuery разбирать полученный кусок html.

Разве что для таких взятых phantomjs страниц надо отдельно авторизацию проходить, и тут, похоже, без casperjs не обойтись.

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


Часовой пояс GMT +3, время: 19:00.