使用 Cheerio 抓取许多网站

Using Cheerio for scraping many sites

我正在使用 cheerio 抓取大约 800 个网站,以获取网站标题。我遇到的第一个问题是有时我会收到一条错误消息 "We’ve encountered an error: Error: socket hang up"。其次,可能是因为 cheerio 的异步性质,当我记录创建的 objects 时,它们都具有数组中最后一个网址的地址。最后,我记录了我一直将 objects 推入的数组,但它实际上是立即将其记录为 [],因为它在执行任何其他操作之前完成了此操作。我该如何解决这三个问题?我去过

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

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

您的 "last web address" 问题是关于范围的经典 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){...});