【问题标题】:delaying requests using request and cheerio modules使用request和cheerio模块延迟请求
【发布时间】:2017-04-21 09:31:22
【问题描述】:

所以这是我用来抓取我的页面的代码(我正在使用 request 和 Cheerio 模块:

for (let j = 1; j < nbRequest; j++)
{
  const currentPromise = new Promise((resolve, reject) => {
    request(
      `https://www.url${j}`,
      (error, response, body) => {
        if (error || !response) {
          console.log("Error: " + error);
        }

    console.log("Status code: " + response.statusCode + ", Connected to the page");

    var $ = cheerio.load(body);
    let output = {
      ranks: [],
      names: [],
      numbers: [],
    };

    $('td.rangCell').each(function( index ) {
      if ($(this).text().trim() != "Rang")
      {
        output.ranks.push($(this).text().trim().slice(0, -1));
        nbRanks = nb_ranks+1;
      }

    });

    $('td.nameCell:has(label)').each(function( index ) {
      output.names.push($(this).find('label.nameValue > a').text().trim());
    });

    $('td.numberCell').each(function( index ) {
      if ($(this).text().trim() != "Nombre")
      {
        output.numbers.push($(this).text().trim());
      }
    });

    console.log("HERE 1");
    return resolve(output);
  }
);


 });
    promises.push(currentPromise);
   }

之后,我使用节点模块解析并将结果保存在 csv 文件中。 在这一点上,我已经能够爬取大约 100 页,但是当涉及到更大的数字(1000+)时,我收到了 500 个响应,这意味着我认为我被踢了。 所以我认为最好的解决方案是延迟请求,但我没有找到解决方案。 你们有任何想法以及代码的外观吗?

【问题讨论】:

    标签: node.js request cheerio


    【解决方案1】:

    您要查找的内容称为“控制流”,例如,您可以使用async.queue 来实现。

    如果您将每个请求都添加到队列中,您可以通过工作人员的数量来控制并行请求的数量。并且可以在请求回调的最后部分添加 setTimeouts 来实现请求的延迟。

    此外,我建议使用“爬虫”包(而不是自己构建),例如npm-crawler 因为他们内置了速率限制,并且已经处理了您接下来可能面临的其他事情:) 例如用户代理池

    更新:

    const async = require("async");
    const delayTime = 1500; //wait 1,5 seconds after every new request
    
    getRequestPromise(csvLine){
     return new Promise( make you request here );
    }
    
    const asyncQueue = async.queue(function(task, callback) {
     getRequestPromise(task).then(_ => {
      setTimeout(() => {
       callback(null);
      }, delayTime);
     });
    }, 1); //1 one request at a time
    
    for(csv){ //pseudo
     asyncQueue.push(csv[i], () => {});
    }
    
    asyncQueue.drain = () => {
     console.log("finished.");
    };
    

    【讨论】:

    • 我想我已经通过为每个请求创建一个承诺来“控制流程”。在我的 csv 文件中,我按照想要的顺序接收数据。现在我的目标是在每个之间添加一个延迟。
    • 不是真的,你只是在“控制秩序”,你的承诺会同时得到解决。
    • 为 async.queue 得到了它,但你能帮我把 setTimeout 添加到请求回调的最后部分吗?
    • 您好 Ezdin,我已经使用 delayTime 的代码示例更新了我的答案。
    猜你喜欢
    • 2012-09-17
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 2013-11-17
    相关资源
    最近更新 更多