2016-08-07 1 views
2

Je suis en train de créer un robot d'indexation qui couvrira plus de 200 sites. Le code que j'ai actuellement est exécuté sur un fichier JSON externe que j'ai construit d'une douzaine de sites. Exemple:NightmareJS - Web Crawler a besoin d'itérer sur les données JSON

[ 
    { 
    "company": "My Company", 
    "url": "http://example.com/jobs/", 
    "query": "div.job-listings>dt a", 
    "link": "div.job-listings>dt a" 
    }, 
    { 
    "company": "Another Company", 
    "url": "http://anothercompany.com/careers/", 
    "query": ".clearfix~ .col-sm-6+ .col-sm-6 a , .col-sm-6:nth-child(4) a", 
    "link": ".clearfix~ .col-sm-6+ .col-sm-6 a , .col-sm-6:nth-child(4) a" 
    } 
] 

Quand j'ai essayé async .each il vous connecter tous les objets originaux en haut de la fonction avant de tenter d'entrer dans l'instance de cauchemar, puis revenir error Nothing responds to "goto". Puis j'ai essayé async .eachSeries, qui imprime le résultat correct mais s'arrête après la première itération.

var async = require ('async'); 
var data = require('./input.json') 
var Nightmare = require('nightmare'); 
var nightmare = Nightmare({ show: false }) 

function crawl(data, cb) { 
    console.log(data) // When async.each will iterate all items then error 
    var nightmare = new Nightmare() 
    nightmare 
    .goto(data.url) // go to JSON specified url 
    .wait(data.query) // wait until CSS selector loads 
    .evaluate(function (data) { 
     positionsArr = [] 
     obj = {} 
     obj.company = data.company 
     query = document.querySelectorAll(data.query) 
     link = document.querySelectorAll(data.link) 
    /* Set query and link equal to all elements with selector 
    itearte through appending text (innerText) from each element 
    with job url to obj*/ 
     var i; 
     for (i = 0; i < query.length; i++) { 
    positionsObj = {} 
    positionsObj.title = query[i].innerText.trim() 
     // if each position has individual page 
     if (data.link !== null) { 
     positionsObj.url = link[i].href 
     } else { 
      positionsObj.url = data.url 
     } 
    positionsArr.push(positionsObj) 
     } 
     obj.positions = positionsArr 
     return obj 
    }, data) 
    .end() 
    .then(function (obj) { 
    console.log(obj) 
    console.log('done') 
    }) 
    .catch(function (error) { 
    console.error('error', error); 
    }); 
} 


async.eachSeries(data, crawl, function (err){ 
    console.log('done!'); 
}) 

Comment puis-je avoir ce travail sans avoir à écrire un fichier individuel pour chacun? Ou y a-t-il un meilleur moyen d'explorer cette quantité de sites?

Source code

Répondre

1

Vous devez utiliser la fonction de rappel (cb) si vous voulez exécuter la deuxième étape et ainsi de suite:

.end() 
.then(function (obj) { 
    console.log(obj); 
    console.log('done'); 
    cb(); 
}) 
.catch(function (error) { 
    console.error('error', error); 
    cb(error); 
});