2017-02-12 6 views
1

Задача

Я пытаюсь очистить изображения и автоматизировать разбиение на страницы. Я использую span описание элементов на странице и общее количество элементов: 1 - 20 of 83,829 results. Я хочу, чтобы кошмар пробежал этот цикл, но он висит и дает мне ошибку Javascript heap out of memory. Есть ли способ сделать это выполнение каждый раз, а не нажимать на стек, потому что я чувствую, что это то, что он делает.как выполнять ночные коты в петле while

код исправить

function scrapeEach(paginate) { 
// while paginate has next scrapeEach 
while (paginate.next) { 
    nightmare 
    .wait(4000) 
    .realClick('#pageNext .results-next') 
    .wait(4000) 
    .evaluate(() => { 
     return document.body.innerHTML 
    }) 
    .then(result => { 
     scrapeImages(result); 
     paginate.update(); 
     paginate.state(); 
    }) 
    .catch(error => { 
     console.error('Search failed:', error); 
    }); 
    } 
return nightmare.end() 
} 

Вот дополнительный код, который работает с scrapeEach(), Я создал этот объект а постраничной отслеживать страницы, как это:

function Paginate(url, pgd) { 

    this.url = url; 
    this.array = pgd.split(" "); 

    this.currentPage = Number(this.array[0]); 
    this.totalItems = Number(_.join(_.filter(this.array[4], char => char != ","), '')); 
    this.itemsPerPage = Number(this.array[2]); 
    this.totalPages = Math.floor(this.totalItems/this.itemsPerPage) 
    this.next = true; 

    this.update =() => { 
    this.currentPage += 1; 
    if (this.currentPage >= this.totalPages) 
    this.next = false; 
    } 

    this.state =() => { 
    console.log("-------- Pagination ----------") 
    console.log("current page: " + this.currentPage); 
    console.log("total pages: " + this.totalPages); 
    console.log("total items: " + this.totalItems); 
    console.log("items per page: " + this.itemsPerPage); 
    console.log("has next page: " + this.next); 
    console.log("------------------------------\n"); 
    } 
} 

Это очищает изображения от одна страница

// scrapes all image data on one page and updates to db 
function scrapeImages(html) { 
    xr(html, '#returns > li', [ 
    { 
    img: 'dl.return-art > dd > a > [email protected]', 
    title: 'dl.return-art > dt > [email protected]', 
    created: 'dl.return-art > .created', 
    medium: 'dl.return-art > .medium', 
    dimensions: 'dl.return-art > .dimensions', 
    credit: 'dl.return-art > .credit', 
    accession: 'dl.return-art > .accession' 
    } 
    ])((err, res) => { 
    if (err) 
    throw err; 
    Artwork.addArt(res); 
}) 
} 

Эта функция sta RTs весь процесс

// the onview endpoint 
function onView() { 
    nightmare.goto(config.NGA.online) 
    nightmare 
    .wait(3000) 
    .evaluate(() => { 
     return [document.location.href, document.querySelector('span.results-span').innerHTML] 
    }) 
    .then(([url, pgd]) => scrapeEach(new Paginate(url, pgd))) 
    } 

Сообщение об ошибке

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 
1: node::Abort() [/usr/local/bin/node] 
2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node] 
3: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/local/bin/node] 
4: v8::internal::Factory::NewRawOneByteString(int, v8::internal::PretenureFlag) [/usr/local/bin/node] 
5: v8::internal::Factory::NumberToString(v8::internal::Handle<v8::internal::Object>, bool) [/usr/local/bin/node] 
6: v8::internal::Runtime_NumberToStringSkipCache(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node] 
7: 0x18caa0a079a7 
8: 0x18caa0f37cbc 
Abort trap: 6 

ответ

0

Так что я понял это. Проблема заключалась в асинхронном выпуске цикла while, который выполнялся асинхронно, пока он не завершился, и тогда экземпляр кошмара никогда не будет запущен. Я обновил свое решение от автоматизации нажатия на следующую страницу до вычисления следующей страницы в URL-адресе &pageNumber= и передачи данных о странице, URL-адресах и элементах на странице с помощью специального объекта страницы для этого сайта. Я также добавил некоторые данные для отладки для отображения.

function Paginate(url, pgd) { 

this.url = url; 
this.array = pgd.split(" "); 

this.currentPage = Number(this.array[0]); 
this.totalItems = Number(_.join(_.filter(this.array[4], char => char != ","), '')); 
this.itemsPerPage = Number(this.array[2]); 
this.totalPages = Math.floor(this.totalItems/this.itemsPerPage) 
this.next = true; 

this.update =() => { 
    let chunks = url.split("&").filter(segment => !segment.includes('Number=')); 

    this.currentPage += 1; 
    if (this.currentPage >= this.totalPages) 
     this.next = false; 

    this.url = _.join(chunks, "") + '&pageNumber=' + this.currentPage; 
} 

this.state =() => { 
    console.log("-------- Pagination ----------") 
    console.log("current page: " + this.currentPage); 
    console.log("total pages: " + this.totalPages); 
    console.log("total items: " + this.totalItems); 
    console.log("items per page: " + this.itemsPerPage); 
    console.log("has next page: " + this.next); 
    console.log("current url: " + this.url); 
    console.log("------------------------------\n"); 
} 

} 

я использовал асинхронном-х whilst использовать время цикла синхронно и выполнить кошмар над каждой итерации.

function scrapeEach(paginate) { 
    // while paginate has next scrapeEach 
    let hasNext =() => paginate.next && paginate.currentPage < 10 
    async.whilst(hasNext, next => { 

    nightmare 
    .goto(paginate.url) 
    .wait(4000) 
    .evaluate(() => { 
     return document.body.innerHTML 
    }) 
    .then(result => { 
     scrapeImages(result); 
     paginate.update(); 
     paginate.state(); 
     next(); 
    }) 
    .catch(error => { 
     console.error('Search failed:', error); 
    }); 
    }, err => { 
    if (err) 
     throw err; 
    console.log("finished!"); 
    }) 
    return nightmare; 
} 
0

Ограничить процессов, выполняющихся параллельно

var limit = 10;  // concurrent read // this can be increased 
    var running = 0; 

    function scrapeEach(paginate) { 
    // while paginate has next scrapeEach 
    while (paginate.next && running < limit) { 
     running++; 
     nightmare 
     .wait(4000) 
     .realClick('#pageNext .results-next') 
     .wait(4000) 
     .evaluate(() => { 
      return document.body.innerHTML 
     }) 
     .then(result => { 

      scrapeImages(result , function(){ 

      paginate.update(); 
      paginate.state(); 
      running--; 

      }); 
     }) 
     .catch(error => { 
      console.error('Search failed:', error); 
      running--; 
     }); 
     } 
    return nightmare.end() 
    } 


    // scrapes all image data on one page and updates to db 
    function scrapeImages(html ,cb) { 
     xr(html, '#returns > li', [ 
     { 
     img: 'dl.return-art > dd > a > [email protected]', 
     title: 'dl.return-art > dt > [email protected]', 
     created: 'dl.return-art > .created', 
     medium: 'dl.return-art > .medium', 
     dimensions: 'dl.return-art > .dimensions', 
     credit: 'dl.return-art > .credit', 
     accession: 'dl.return-art > .accession' 
     } 
     ])((err, res) => { 
     if (err) 
     throw err; 
     Artwork.addArt(res); 
     cb(); 
    }) 
    } 
+0

Я не уверен, как это использовать, у меня есть условие, которое должно выполняться в цикле 'while', а затем автоматизирует щелчок на следующей странице, если есть следующая страница. –

+0

который состояние? –

+0

условие, что есть следующая страница, если есть, то нажимает на следующую кнопку –

Смежные вопросы