使用Cheerio来抓取许多网站

时间:2016-01-27 18:40:53

标签: javascript node.js cheerio

我正在使用cheerio来搜索大约800个网站,以获取网站标题。我遇到的第一个问题是,有时我收到一条错误消息,说'&34;我们遇到了错误:错误:socket挂断"。其次,可能由于cheerio的异步性质,当我记录创建的对象时,它们都具有数组中最后一个Web地址的地址。最后,我记录了我一直在推送对象的数组,但它实际上是将其作为[]立即记录,因为它在完成任何其他操作之前完成了此操作。我该如何解决这三个问题?我已经

var tempArr = [];
var completedLinks = ["http://www.example.com/page1", "http://www.example.com/page2", "http://www.example.com/page3"...];

for (var foundLink in completedLinks){

  if(ValidURL(completedLinks[foundLink])){

    request(completedLinks[foundLink], function (error, response, body) {

      if (!error) {
        var $ = cheerio.load(body);
        var titles = $("title").text();

        var tempObj = {};
        tempObj.title = titles;
        tempObj.address = completedLinks[foundLink]

        tempArr.push(tempObj);

        console.log(tempObj)
      }else{
        console.log("We’ve encountered an error: " + error);
      }    

    });

  }
}
console.log(tempArr);

1 个答案:

答案 0 :(得分:2)

您的挂机可能是因为许多网站实施了速率限制。我猜这些错误往往发生在网站的第2页。您可能想要做的一件事是按主机将链接组织到列表中,并使用setTimeout来限制第一个到该主机之后的每个调用。

您的"最后一个网址"问题是关于范围的经典JavaScript问题。至少你应该在一个函数中处理每个请求:

function processLink(link){
 if(ValidURL(link)...
}

然后

for (var foundLink in completedLinks){ 
  processLink(completedLinks[foundLink]);
}

最后等到所有人都完成后才退出你应该考虑Promises

忽略限制问题:

function processLink(link){
  return new Promise(function(resolve, reject) {
    request(link, function (error, response, body) {
        if (!error) {
          resolve(tempObj);
        }

    });
  });
};

var promises = [];
for (var foundLink in completedLinks){ 
  promises.push(processLink(completedLinks[foundLink]));
}
Promise.all(promises).then(function(tempObjArr){...});