【问题标题】:Improvement on the control flow of node.js scraper for JSON output on large file改进node.js爬虫对大文件JSON输出的控制流程
【发布时间】:2013-11-13 08:38:25
【问题描述】:

我是 Node.js 的异步控制流的新手,我的爬虫工作,但我不禁想到必须有一个更优化(优雅?)的方式来做到这一点,我愿意使用其他节点库。更具体地说:

  1. 我觉得当前的控制流(带有所有回调)很难阅读,但也许只是因为这对我来说是新的。好像有几个关于控制流的库,我应该使用它吗?
  2. 最初,我的代码首先将所有request 解析并保存在records = [] 上,然后处理后将所有内容写入文件。我在这里更改了代码,以便它为 for 循环中的每条记录提供request - parse - append,我想确认这种方法对于大量请求是否更好。
  3. 用JSON格式写记录有些痛苦,目前我必须先调用startStep来附加[,然后使用(flag? function(){flag = false; return "";}() : ",")来判断是否是第一条记录,如果不是先附加逗号,然后追加所有记录,然后在末尾追加]。同样,我很好奇是否有更好的方法来做到这一点。
  4. 要进行迭代,我在全局范围内声明列表,并使用list.shift() 迭代下一项,现在似乎没问题,但我认为这会导致大规模的副作用。我的直觉是我应该将数组作为参数传递。再次,我想确认这一点。

    var fs = require('fs');
    var request = require("request");
    var cheerio = require("cheerio");
    
    function appendFile(_input, callback){
      fs.appendFile("./TED/alltalk3.json", _input, function(err){
        if(err){
          console.log("input is" + _input + "error is :" + err);
        }
        else{
          callback();
        }
      });
    }
    
    function startStep(){  
      appendFile("[", function(){
        console.log("--start--");
        getOneDay(list.shift());
      })  
    }
    
    function finalStep(){
      appendFile("]", function(){
        console.log("--end--");
        return;
      })
    }
    
    
    var flag = true; // first item no comma
    function getOneDay(itm){  
      if(itm){      
        request("http://www.ted.com/talks/view/id/" + itm, function(error, response, body) {
          var $ = cheerio.load(body)
          var record = {};
          record["title"] = $("#altHeadline").text();
    
          appendFile(
            (flag? function(){flag = false; return "";}() : ",") + (JSON.stringify(record, null, 4)), 
            function(){
              return getOneDay(list.shift());;
            }
          )
        });    
      }
      else{
        return finalStep();
      }
    }
    
    var list = [];
    for(var i = 1; i < 5; i++){
      list.push(i);
    }
    startStep();
    

【问题讨论】:

    标签: javascript node.js asynchronous web-scraping


    【解决方案1】:

    您尝试使用代码实现的是Finite State Machine (FSM),这是异步编程中使用的一种常见模式。某些语言具有内置支持。例如,C# 5.0 有async/await,它通过为我们提供熟悉的线性代码流,极大地简化了异步编程。

    已经有一些attemptsasync/await 引入JavaScript。我相信,Node.js 和所有主流网络浏览器对它的全面支持只是时间问题。

    在那之前,JavaScript 中最常见的异步代码流模式是Promise。它表示将在未来完成的操作的结果,并允许在完成后使用 JavaScript 回调函数采取行动。我建议您在代码中坚持这种模式。

    更多资源:

    【讨论】:

      【解决方案2】:

      强烈建议您查看https://github.com/caolan/async——尤其是它的 forEachSeries 方法——它看起来正是您所需要的。

      我还可以推荐在这种特殊情况下使用 fs 同步方法。不建议对服务使用阻塞方法,但对于类似 shell 的脚本是可以的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多