2016-02-28 51 views
0

我正在尝试制作抓取IMDB并列出电影名称和分级的网络抓取工具。这是我的index.js文件。 假设我正在抓取10部电影。然后,我将抓取的结果保存在不同的文件中,如'message.txt'。现在我想发送这个message.txt文件作为对任何请求的响应。但是每当我提出请求时,最初都会向我的浏览器发送一个空文件。然后我注意到,抓取的结果保存在message.txt文件中需要一些时间。我认为这是因为所有操作在nodejs中都是异步的。那么只有在抓取完成后才能发送message.txt文件?动作完成后需要发送响应

var express = require('express'); 
 
var app = express(); 
 

 
var cheerio = require('cheerio'); 
 
var request = require('request'); 
 
var fs = require('fs'); 
 

 
app.listen(8080); 
 
console.log('Running'); 
 

 

 
app.get('/', function(req, res) { 
 
    console.log('Recieved the get Request'); 
 
    var i = 1; 
 
    var count = 0; 
 
    while (count < 10) { 
 
    var url = 'http://www.imdb.com/title/tt' + i + '/'; 
 
    console.log(url); 
 
    count = count + 1; 
 
    i = i + 1; 
 
    request(url, function(error, response, html) { 
 
     if (!error) { 
 
     var $ = cheerio.load(html); 
 
     var title, ratings, released; 
 
     var json = { 
 
      title: '', 
 
      ratings: '', 
 
      released: '' 
 
     }; 
 
     $('.title_wrapper').filter(function() { 
 
      var data = $(this); 
 
      json.title = data.children().first().text().trim(); 
 
      json.released = data.children().last().children().last().text().trim(); 
 
     }); 
 
     $('.ratingValue').filter(function() { 
 
      var data = $(this); 
 
      json.ratings = parseFloat(data.text().trim()); 
 
     }); 
 
     console.log(json); 
 
     fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) {}); 
 
     }; 
 
    }); 
 
    }; 
 
    res.sendFile(__dirname + '/index.js'); 
 
});

+0

使用的承诺 - 回调,当FS流完成后保存文件拨打电话发送文件。 –

+0

你可以解释更多@GandalftheWhite – Mohit

+0

我希望可以帮助 –

回答

0

可以使用异步包,它是伟大的控制流量,喜欢的东西:

console.log('Recieved the get Request'); 
    var i = 1; 
    var count = 0; 
    while (count < 10) { 
    var url = 'http://www.imdb.com/title/tt' + i + '/'; 
    console.log(url); 
    count = count + 1; 
    i = i + 1; 
    async.waterfall([ 
     function sendRequest (callback) { 
      if (!error) { 
       var $ = cheero.load(html); 
       var json = { 
        title: '', 
        ratings: '', 
        released: '' 
       } 
      } 
      $('.title_wrapper').filter(function() { 
       var data = $(this); 
       json.title = data.children().first().text().trim(); 
       json.released = data.children().last().children().last().text().trim(); 
      }); 
      $('.ratingValue').filter(function() { 
       var data = $(this); 
       json.ratings = parseFloat(data.text().trim()); 
      }); 
      callback(null, JSON.stringify(json, null, 4) + '\n'); 
     }, 
     function appendFile (json, callback) { 
      fs.appendFile('message.txt', json, function(err) { 
       if (err) { callback(err); } 
       callback(); 
      }); 
     } 
    ], function(err) { 
     res.sendFile(__dirname + '/index.js'); 
    }); 
+0

是否使用'async'并行包。找到这个链接非常有用[在所有异步请求被调用并执行后执行某个函数](http://stackoverflow.com/a/16866080/3717234) – Mohit

0
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) { 
//This part is executed after the process has been completed 
}); 

你必须做一个回调那里该部分将在已执行的操作只调用。

我们利用这里的回调函数,虽然没有任何具体的回调,除了我们的情况下的err,我们并不需要其他任何其他的。

请尝试。

0

fs.appendFile()是异步的,所以当函数返回时,您附加到文件的内容将不会立即存在。因此,如果您想阅读将该文件发送给用户,则需要在您提供给fs.appendFile()的回调内进行。

app.get('/', function(req, res) { 
... 
     fs.appendFile(
      'message.txt', 
      JSON.stringify(json, null, 4) + '\n', 
      function(err) { 
      if (err) { 
       // Log the error and send a message to the user here 
       return; 
      } 
      res.sendFile(__dirname + '/index.js') 
      } 
     ); 
     }; 
    }); 
    }; 
}); 

您可能会试图使用fs.appendFileSync()代替。这对于命令行工具来说很好,但是因为这是一个Web服务器,所以不要这样做。它将在发生I/O时锁定线程。

+0

每个'request()'将返回1个json。假设我调用request()10次,那么在写入message.txt文件之后可能会发生'res.sendFile'被触发。所以剩下的9个jsons不会被追加。所以如何确保在所有的request()调用完成之后,只有文件会被发送到浏览器 – Mohit