Я запускаю следующий скрипт с CasperJS, и примерно через 1/3 пути через массив он начинает работать из пространства подкачки, и машина становится очень медленной. Что я здесь делаю неправильно?
searchPages
- это массив из 54 номеров, соответствующих значению URL для страницы поиска.
casper.each(searchPages,function(casper,index){
loadSearch(casper,index);
});
function loadSearch(casper,index){
var currentTime = new Date();
var month = currentTime.getMonth() + 2;
var day = currentTime.getDate();
var year = currentTime.getFullYear();
var dateStart = month + "/" + day + "/" + year;
month = currentTime.getMonth() + 3;
var dateEnd = month + "/" + day + "/" + year;
casper.thenOpen(url,function(){
var myfile = "data-"+year + "-" + month + "-" + day+".html";
this.evaluate(function(j) {
document.querySelector('select[name="searchParameters.localeId"]').selectedIndex = j;
},index);
this.evaluate(function(start) {
$("#leaveDate").val(start);
},dateStart);
this.evaluate(function(end) {
$("#returnDate").val(end);
},dateEnd);
this.evaluate(function() {
$("#OSB_btn").click();
});
this.waitForSelector('#destinationForPackage', function() {
if (this.exists('#destinationForPackage')){
var name = casper.evaluate(function() {
return $("#destinationForPackage option[value='" + $("#destinationForPackage").val() + "']").text()
});
if (name != "Going To"){
if (name == null){
console.log("it null");
}else{
name = name.replace("/","_");
casper.capture('Captures/Searches/search_' + name + '.jpg');
console.log("Capturing search_" + name);
}
}
}else{
console.log("Still doesn't exist...retry");
loadSearch(casper,index);
}
},function(){
console.log("Search page timed-out.");
},20000);
});
}
И он добавляет около 3 ГБ за цикл.
Ну, оказывается, это очень известная проблема с PhantomJS. 3+ лет как открытая ошибка, и, видимо, это как-то связано с QT Webkit. Тем не менее, я смог решить эту проблему, закрыв каждую страницу во время цикла и вновь открыв новую страницу Phantom. Это немного хакерская работа, но потребление памяти намного меньше. Однако, примерно через 200 страниц, он по-прежнему имеет довольно высокую память (1GB+). Итак, я разбиваю свои скрипты на блоки из 200 и начинаю следующий после завершения. Вот готовый продукт, который успешно завершается без чрезмерного использования памяти. По какой-то причине он использует меньше на MacOS, чем Windows.
casper.start(url,function(){
this.echo('continuing captures...');
}).each(searchPages,function(casper,index){
loadSearch(this,index);
});
function loadSearch(casper,index){
var currentTime = new Date();
var month = currentTime.getMonth() + 1;
var day = currentTime.getDate() + 1;
var year = currentTime.getFullYear();
var dateStart = month + "/" + day + "/" + year;
var fortnightAway = new Date(+new Date + 12096e5);
var dateEnd = fortnightAway.getMonth() + 1 + "/" + fortnightAway.getDate() + "/" + fortnightAway.getFullYear();
casper.page.close();
casper.page = require('webpage').create();
casper.thenOpen(url,function(){
var myfile = "data-"+year + "-" + month + "-" + day+".html";
this.evaluate(function(j) {
document.querySelector('select[name="searchParameters.localeId"]').selectedIndex = j;
},index);
this.evaluate(function(start) {
$("#leaveDate").val(start);
},dateStart);
this.evaluate(function(end) {
$("#returnDate").val(end);
},dateEnd);
this.evaluate(function() {
$("#OSB_btn").click();
});
this.waitForSelector('#destinationForPackage', function() {
if (this.exists('#destinationForPackage')){
var name = casper.evaluate(function() {
return $("#destinationForPackage option[value='" + $("#destinationForPackage").val() + "']").text()
});
if (name != "Going To"){
if (name == null){
console.log("it null");
}else{
name = name.replace("/","_");
name = name.replace("/","_");
casper.capture('Captures/Searches/search_' + name + '.jpg');
console.log("Capturing search_" + name);
}
}
}else{
console.log("Search failed to load. Retrying");
loadSearch(casper,index);
}
},function(){
console.log("Search page timed-out. Retrying");
loadSearch(casper,index);
},20000);
});
}
Возможно, было лучшее решение исходной проблемы, но для быстрого исправления setTimeout
памяти попробуйте setTimeout
сделать рекурсивный вызов без извлечения стека...
setTimeout(() => loadSearch(casper,index), 0);
(Эта идея предполагает, что проблема с памятью является результатом слишком большой рекурсивной глубины в течение длительного времени ожидания).