2016-07-09 15 views
0

Ich möchte Multi-Site mit einem erholsamen api schrotten, verwende ich Express, um es zu implementieren. Aber ich nur ausgelöst Alptraum erfolgreich in erstem Mal mit meinem api, wenn ich wieder ich meine api rufe nicht Alptraum auslösen kann mehr :(Verwenden Sie erholsame api, um Albtraum-Scraping Multi-Site mit Versprechen Wrapper

hat eine Idee?

eine andere Frage, in folgendem Fall, ich brauche Objekt neuen Albtraum individuell instanziiert, so dass ich drei verschiedene Website Schrott kann, habe keinen intelligenteren Weg, das zu erreichen

Balg getScrap meine apiControler Funktion mit ausdrücklichem Router GET Rückruf ist, Sie auch im Kern überprüfen könnten?: https://gist.github.com/sevenLee/7091f8c56ccad3c0551b512f725af7da

import Nightmare from 'nightmare'; 
import cheerio from 'cheerio'; 

let nightmare = Nightmare({show: false}); 
let nightmare2 = Nightmare({show: false}); 
let nightmare3 = Nightmare({show: false}); 

const urlObject = { 
    site1: 'http://www.site1.com', 
    site2: 'http://www.site2.com', 
    site3: 'http://www.site3.com' 
}; 

export function getScrap(req, res){ 
    let result = {}; 

    result.site1 = { 
    topList: [] 
    }; 
    result.site2 = { 
    topList: [] 
    }; 
    result.site3 = { 
    topList: [] 
    }; 

    const pro1 = Promise.resolve(
    nightmare 
     .goto(urlObject.site1) 
     .wait(200) 
     .evaluate(() => { 
     console.log('site1 into evaluate'); 
     return document.querySelector('.ninenine').innerHTML; 
     }) 
     .end() 
) 
    .then((html) => { 
    let $ = cheerio.load(html); 
    let tt = $('.horizontal-li'); 
    let sections = $(".section-board-title"); 

    sections.each((index, elm) => { 
     if($(elm).text() === 'TopList'){ 
     $(elm).next('ul').find('li').each((index, elm_li) => { 
      let title =$(elm_li).find('.cabinet-instruction').text(); 
      let price =$(elm_li).find('.cabinet-middle .price').text(); 
      let imgSrc = $(elm_li).find('.cabinet-img').attr('data-temp-src'); 
      if(title !== '' && price !==''){ 
      result.site1.topList.push({ 
       title, 
       price, 
       imgSrc 
      }); 
      } 
     }); 
     } 
    }); 
    }) 
    .catch((err) => { 
    console.log('site1 scrap err:', err); 
    return res.status(400).send({reason:'site1 scrap err'}); 
    }); 

    const pro2 = Promise.resolve(
    nightmare2 
     .goto(urlObject.site2) 
     .wait(200) 
     .evaluate(() => { 
     return document.querySelector('.ninenine').innerHTML; 
     }) 
     .end() 
) 
    .then((html) => { 
    let $ = cheerio.load(html); 
    let tt = $('.horizontal-li'); 
    let sections = $(".section-board-title"); 

    sections.each((index, elm) => { 
     if($(elm).text() === 'TopList'){ 
     $(elm).next('ul').find('li').each((index, elm_li) => { 
      let title =$(elm_li).find('.cabinet-instruction').text(); 
      let price =$(elm_li).find('.cabinet-middle .price').text(); 
      let imgSrc = $(elm_li).find('.cabinet-img').attr('data-temp-src'); 
      if(title !== '' && price !==''){ 
      result.site2.topList.push({ 
       title, 
       price, 
       imgSrc 
      }); 
      } 
     }); 
     } 
    }); 
    }) 
    .catch((err) => { 
    console.log('site2 scrap err:', err); 
    return res.status(400).send({reason:'site2 scrap err'}); 
    }); 

    const pro3 = Promise.resolve(
    nightmare3 
     .goto(urlObject.site3) 
     .wait(200) 
     .evaluate(() => { 
     return document.querySelector('#layout').innerHTML; 
     }) 
     .end() 
) 
    .then((html) => { 
    let $ = cheerio.load(html); 
    let sections = $(".pditem"); 

    sections.each((index, elm) => { 

     let title = $(elm).find('.name').text(); 
     let price = $(elm).find('.price').find('span').eq(1).text(); 
     let imgSrc = ['www.site3.com',$(elm).find('li').eq(1).find('img').attr('src')].join(''); 

     result.site3.topList.push({ 
     title, 
     price, 
     imgSrc 
     }); 
    }); 
    }) 
    .catch((err) => { 
    console.log('site3 scrap err:', err); 
    return res.status(400).send({reason:'site3 scrap err'}); 
    }); 


    Promise.all([pro1, pro2, pro3]) 
    .then(values => { 
    res.json(result); 
    }) 
    .catch((err) => { 
    return res.status(500).send({reason:err.toString()}); 
    }); 
} 

Antwort

0

(Von meiner ursprünglichen Antwort auf segmentio/nightmare#715.)

Aber ich nur Alptraum erfolgreich in erstem Mal mit meinem api ausgelöst, , wenn ich meine api wieder anrufen kann ich nicht Alptraum auslösen jeden mehr

Es sieht aus wie Sie Ihre Instanzen außerhalb von getScrap() sind definiert, dann .end() innerhalb von getScrap() Aufruf, die endet und Destr oy die Nightmare/Electron-Instanzen. Sobald sie beendet sind, können sie nicht mehr verwendet werden. Versuchen Sie, die Erstellung Ihrer Nightmare-Instanzen innerhalb der -Methode zu verschieben.

eine andere Frage, in Fall unten, muss ich neue Nightmare-Objekt individuell instanziieren, so dass ich drei verschiedene Website verschrotten kann, haben Sie einen klüger Weg, um das zu erreichen?

Hängt davon ab, was Ihr Anwendungsfall ist. Sie könnten eine einzelne Nightmare-Instanz verwenden und über die URLs iterieren, aber das dauert länger, da die Ausführung von Nightmare sequenziell sein muss. Wenn Sie neugierig sind, wie man so etwas macht, könnte this article from nightmare-examples lohnenswert sein.

Schließlich ist es wahrscheinlich wert, darauf hinzuweisen, dass Sie basierend auf Ihrem obigen Code nicht cheerio verwenden müssen. Sie könnten .evaluate() und CSS-Abfragen verwenden, um zu erreichen, was Sie wollen, denke ich.

+0

Danke, es kann jetzt funktionieren! :) –

+0

Ich werde Albtraum-Beispielartikel auch überprüfen. nettes Tutorial! –