2016-06-11 43 views
1

我正在尝试使用horseman登录到网站,找到一组链接,打开每个链接,刮取一些数据并将其返回。如何使用horseman和nodejs打开一个URL数组?

这里是我迄今为止...

function getLinks() { 
    return horseman.evaluate(function() { 
     var links = []; 
     $('#cards > tbody > tr:not(:first-child) a').each(function (i, el) { 
      links.push($(el).attr('href')); 
     }); 
     return links; 
    }); 
} 

function scrapeDataFromLink(link) { 
    return horseman 
     .open(link) 
     .waitForSelector('#details > fieldset > table') 
     .evaluate(function() { 
      var data = { 
       name: $('#name > td:nth-child(2)').html().trim(), 
       type: $('#type > td:nth-child(2)').html().trim(), 
       expiry: $('#expiry > td:nth-child(2)').html().trim() 
      }; 
      return data; 
     } 
    ) 
} 


horseman 
    .userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0') 
    .open(LOGIN_URL) 
    .type('input[id=username]', username) 
    .type('input[id=password]', password) 
    .click('[id="login"]') 
    .waitForSelector('table[id=cards]') 
    .then(getLinks) 
    .then(function(links){ 
     var promises = []; 

     links.forEach(function(link){ 
      promises.push(scrapeDataFromLink(link)); 

     }); 
     Promise.all(promises).then((result) => { 
      console.log(result); 
     }) 
    }) 

编辑 - 现在我可以回去使用上面的代码的结果,但他们都同样的结果,使用链条的最后一环。我认为发生的事情是每个循环在前一个URL完成之前打开每个URL,因此只返回最后打开的链接的结果。我如何确保这些承诺是同步执行的?

回答

2

我使用workOneByOne功能概述在此question的答案中,以顺序创建和解决承诺。不知道这是否是最好的方式,但它的工作原理。

var scrapedData = [] 

function getLinks() { 
    return horseman.evaluate(function() { 
     var links = []; 
     $('#cards > tbody > tr:not(:first-child) a').each(function (i, el) { 
      links.push($(el).attr('href')); 
     }); 
     return links; 
    }); 
} 

function scrapeDataFromLink(link) { 
    return horseman 
    .open(link) 
    .waitForSelector('#details > fieldset > table') 
    .evaluate(function() { 
     var data = { 
      name: $('#name > td:nth-child(2)').html().trim(), 
      type: $('#type > td:nth-child(2)').html().trim(), 
      expiry: $('#expiry > td:nth-child(2)').html().trim() 
     }; 
     return data; 
     } 
    ) 
} 


function workOneByOne(items, someAsyncFuntionReturningPromise) { 
    var lastResultPromise = items 
     .map(function(item) { 
      return function(previousResult) { 
       if (previousResult) { 
        console.log(previousResult); 
        scrapedData.push(previousResult); 
       } 

       return someAsyncFuntionReturningPromise(item); 
      }}) 
     .reduce(Q.when, Q()); 

    return lastResultPromise; 
} 


horseman 
.userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0') 
.open(LOGIN_URL) 
.type('input[id=username]', username) 
.type('input[id=password]', password) 
.click('[id="login"]') 
.waitForSelector('table[id=cards]') 
.then(getLinks) 
.then(function(links){ 
    workOneByOne(links, scrapeDataFromLink).then(function(result) { 
      scrapedData .push(result); 
      res.setHeader('Content-Type', 'application/json'); 
      res.send(JSON.stringify(scrapedData)); 
     }) 
}) 
0

您可以登录后考虑这个

var links = ["http://link1.com","http://link2.com"]; 

    scrapeData = []; 

     var it = 0; 
    doit(); 

    function doit(){ 
    var Horseman = require("node-horseman"); 

      horseman 
       .userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 
       Firefox/27.0') 
       .open(links[it]) 
       .waitForSelector('#details > fieldset > table') 
       .html('body') 
       .then(function(html){ 

       var $ = cheerio.load(html); 

       data = { 
       name: $('#name > td:nth-child(2)').html().trim(), 
       type: $('#type > td:nth-child(2)').html().trim(), 
       expiry: $('#expiry > td:nth-child(2)').html().trim() 
      }; 

      scrapeData.push(data); 

      it = it + 1; 

      if(it < links.length){ 
      doit(); 
      } 

       return horseman.close(); 

     }); 
相关问题