【问题标题】:Javascript/NodeJS callbacks function and loopJavascript/NodeJS 回调函数和循环
【发布时间】:2017-06-02 23:52:26
【问题描述】:

我用cheeriorequest 制作了一个网络爬虫,现在我正在尝试在一个url 数组上实现一个循环。

不幸的是,我的呼叫和回拨有问题,但我不知道是什么。

这是我的代码:

var getWebData = function(url) {
  var i = 1;
  var data = [];
  for (c = 0; c < url.length; c++) {
    data[i] = request(url[c], function(err, resp, body) {
          console.log('ok');
           if (!err) {
             console.log('there');
             var $ = cheerio.load(body);
             $('.text').each(function(i, element) {
               var jsObject = { name : "", description : "", price: "", categorie: "", pricePerKg: "", capacity: "", weight: "", scrapingDate : "", url: ""};
               var name = 'TESTOK';
               jsObject.name = name;
               data.push(jsObject);
            })
            return data;
         }
         console.log('but');
       });
    i++;
  }
  var json = JSON.stringify(data);
  fs.writeFile('output.json', JSON.stringify(json, null, 4), function(err) {
      console.log('File successfully written!');
  })
}

getWebData(url);
app.listen('8080');

请注意,我的任何调试打印都不会打印。

有谁知道我的代码出了什么问题,我该怎么做才能让它工作?

【问题讨论】:

  • "请注意,我的任何调试打印都已打印..." - 打印了什么?此外,data 将在 JSON.stringify(data) 中未定义,因为您没有考虑异步性。
  • url 是 url @eLRuLL 的 [ ]
  • 对不起,我的任何印刷品都没有印刷@DanielB

标签: javascript jquery node.js web-scraping cheerio


【解决方案1】:

请求是 Aysnc

var json = JSON.stringify(data);
fs.writeFile('output.json', JSON.stringify(json, null, 4), function(err) {
  console.log('File successfully written!');
})

上面的代码在 for 循环完成执行并填充数据对象之前运行。 循环完成后尝试执行这段代码。

先运行这个命令 npm install async --save

    var async = require('async');

    var getWebData = function(url){
    var data = [];
    async.eachSeries(url, function(urlSingle , cb){
       request(urlSingle, function(err, resp, body) {
        //write your logic here and push data in to data object
        cb();
       })
    },function(){
     // this will rum when loop is done
     var json = JSON.stringify(data);
        fs.writeFile('output.json', JSON.stringify(json, null, 4),         function(err) {
            console.log('File successfully written!');
        });
    });
    }

【讨论】:

  • 感谢您的回答 Asif Saeed,您能告诉我该怎么做吗?
  • 非常感谢 Asif,你能告诉我我必须在哪里增加我的 c 变量吗?我猜是在请求电话之外?
  • 哦,我错过了在 async.eachSeries 之前启动 c=0 并在我写了你的逻辑的请求正文的末尾增加它
  • 好的,我正在尝试,它缺少一个括号,可能在请求正文 @Asif 之后?
  • 不需要c变量
【解决方案2】:
for (c = 0; c < url.length; c++) {
    ……
}

你应该这样改:

var async = require('asycn');
async.map(url,
function(item, callback) {
    data[i] = request(url[c],
    function(err, resp, body) {
        console.log('ok');
        if (!err) {
            console.log('there');
            var $ = cheerio.load(body);
            $('.text').each(function(i, element) {
                var jsObject = {
                    name: "",
                    description: "",
                    price: "",
                    categorie: "",
                    pricePerKg: "",
                    capacity: "",
                    weight: "",
                    scrapingDate: "",
                    url: ""
                };
                var name = 'TESTOK';
                jsObject.name = name;
                data.push(jsObject);
            }) callback(err, data);
        }
        console.log('but');
    });
    i++;
},function(err, results) {
    if(err){
        console.log(err);
    }
});

在循环中是一个耗时的操作。你应该使用异步操作。

【讨论】:

    【解决方案3】:

    我一直在阅读 Asif 的答案和 cmets。该实现是正确的,但您不必增加 c 变量,此外,如果您之前启动 c=0,所有请求都将发送到 url[0]。

    注意 async.eachSeries 在“urlsingle”回调中回调数组 url 的每个元素,所以你应该使用

    request(urlsingle, ...
    

    或考虑使用 async.eachOf,它可以为您提供数组中每个元素的索引。

    检查异步文档是否有任何疑问http://caolan.github.io/async/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-28
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 2013-12-11
      • 2018-04-07
      相关资源
      最近更新 更多