【问题标题】:How to open an array of URLs using horseman and nodejs?如何使用 horseman 和 nodejs 打开 URL 数组?
【发布时间】:2016-06-11 14:01:28
【问题描述】:

我正在尝试使用horseman 登录网站,找到一组链接,打开每个链接,抓取一些数据并返回。

这是我目前所拥有的......

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);
        })
    })

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

【问题讨论】:

    标签: javascript node.js web-scraping phantomjs


    【解决方案1】:

    我使用question 的答案中概述的 workOneByOne 函数来顺序创建和解决承诺。不确定这是否是最好的方法,但它确实有效。

    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 ));
            })
    })
    

    【讨论】:

      【解决方案2】:

      登录后可以考虑这个

      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();
      
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-09
        • 1970-01-01
        • 1970-01-01
        • 2012-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多