Во время работы с PhantomJS у вас не получиться использования метод open() внутри цикла. В этой записи я покажу почему эта проблема происходит и как её решить.
Почему цикл не работает?
Давайте представим, что у вас массив ссылок на разные сайты и вы хотите зайти по каждой из них и скопировать все что есть на нем.
Ниже в этом посте я представлю полноценный рабочий пример для решения этой проблемы.
Если вы просто пройдетесь с помощью цикла, например for
, то у вас ничего не получиться, потому что цикл не будет ждать пока завершиться запрос на сайт и сразу же пойдет на следующий круг и т.д.
Решение проблемы
Ниже представлено решение в виде рекурсивной функции recursiveRun
.
Как она работает?
Я выделю самые важные моменты в коде, если у вас останутся вопросы — задавайте их в комментарии.
- На 20 строке мы запускаем 0 (нулевую, то есть первую) итерацию с позицией
i
, максимальное количество повторений взяли от длинны массива и третий аргумент — это сам массив. - На 24-28 строке мы сравниваем если текущий индекс равен максимальному (длинне массива), то пишем в консоль «Конец» и закрываем текущую сессию PhantomJS. Это случиться когда скрипт пройдется по всему списку ссылок и скопирует с них данные, если они будут доступны.
- Если не удалось зайти по текущей ссылке, то пробуем зайти по следующей (строка 37)
- Записываем текст страницы в
text
на 42 строке и далее на 47 сохраняем текст в файл. Если в файле что-то уже есть, например текст с другого сайта, то он просто добавится к текущему. - В конце переходим на следующий сайт (строка 49).
'use strict'; var page = require('webpage').create(), fs = require('fs'); var log = "[LOG ------->] "; page.settings.loadImages = false; page.settings.resourceTimeout = 20000; page.settings.userAgent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36'; // Массивы ссылок var array = [ "https://google.com", "https://yandex.ru", "http://bologer.ru", "https://bing.com" ]; recursiveRun(0, array.length - 1, array); var recursiveRun = function(i, max, array) { if (i === max) { console.log(log + 'Конец'); phantom.exit(); return; } page.open(array[i], function (status) { page.viewportSize = { width: 1024, height: 900 }; if (status !== "success") { console.log(log + "Ошибка, не удалось зайти на - " + array[i]); recursiveRun(i + 1, max, array); } else { // Дадим 5 сек для загрузки сайта setTimeout(function() { var text = page.evaluate(function() { return document.body.innerText.trim(); }); // Записываем данные с сайта в текстовый файл fs.write("res.txt", "ССЫЛКА: " + array[i] + "\r\n\r\n" + text + "\r\n\r\n\r\n\r\n===============\r\n\r\n", 'a'); recursiveRun(i + 1, max, array); console.log(log + "running next, index -> " + i); console.log(log + "======================================= "); }, 5000); } }); };
В консоли, во время выполнения скрипта вы должны увидеть что-то подобное (я это делал через Windows):
Это означает, что i
по позиции 0, 1 и 3 сработали. И четвертый тоже успешно прошел, только об этом не написало в консоли, потому что условие i == max
сработало и остановило весь процесс рекурсивной функции.
В самом конце консоль вывела какие-то непонятные каракули, что это?
Это обычный вывод русских символов, так выглядит слово «Конец» в Windows консоли :D
Именно поэтому я написал некоторые console.log()
сообщения на английском, чтобы хоть какой-то презентабельный вид был у вывода в консоль, ну и вам было понятнее смотря на скриншот.