【问题标题】:How to (Properly) add in each execution of a loop in node.js如何(正确)在 node.js 中添加循环的每次执行
【发布时间】:2021-03-11 11:06:45
【问题描述】:

所以我正在尝试编写一个谷歌解析器。 我的工具的想法是它接受搜索查询并在谷歌搜索它们并返回 URL。到目前为止它运行良好,但现在我尝试设置页面配置并且遇到问题,我的代码是:

const needle = require("needle") //for making get request
const sp = require("serp-parser") //for parsing data from the request
const queryup = "watch movies online free" //my search data
const query = encodeURI(queryup) //my search data so google can read it
var page = 0; //initializing the page counter
let pages = 5; //setting amount of pages to loop through
for (var i = 0; i < pages; i++) { //my loop
  needle.get(`https://www.google.com/search?q=${query}&start=${page}`, function(err, response){ //MY MAIN PROBLEM <<<--- The issue is its adding to the page value but its not effecting it here, why?
    page += 10 //adding to page value (every 10 page value is 1 extra page)
    console.log(`----- Page number: `+ page / 10+" -----") //logging the number of the page to confirm that it is indeed increasing the page value
    let results = response.body; //defining the body of my request
    parser = new sp.GoogleNojsSERP(results); //initializing the parser
    let parsed = parser.serp //parsing the body
    let objarray = parsed.organic; //parsed body (returns as an array of json objects)
    for (var i = 0; i < objarray.length; i++) { //loop the logging of each url
      let url = objarray[i].url //defining url
      console.log(url) //logging each url
    }
  });
}

没有十亿厘米:

const needle = require("needle") 
const sp = require("serp-parser") 
const queryup = "watch movies online free"
const query = encodeURI(queryup) 
var page = 0;
let pages = 5; 
for (var i = 0; i < pages; i++) {
  needle.get(`https://www.google.com/search?q=${query}&start=${page}`, function(err, response){ 


    //^^^^^ MY MAIN PROBLEM <<<--- The issue is its adding to the page value but its not effecting it here, why?



    page += 10 
    console.log(`----- Page number: `+ page / 10+" -----")
    let results = response.body;
    parser = new sp.GoogleNojsSERP(results);
    let parsed = parser.serp
    let objarray = parsed.organic;
    for (var i = 0; i < objarray.length; i++) {
      let url = objarray[i].url
      console.log(url)
    }
  });
}

【问题讨论】:

    标签: javascript node.js loops google-chrome parsing


    【解决方案1】:

    这似乎是异步的问题。 我对needle不熟悉,但我知道外部查询基本上是不同步的。

    您遇到的问题基本上是,实际的网络查询是在循环第一次运行之后发生的,并且已经将page 增加到 50。然后,构造了 5 个查询,每个查询的 page=50,因为异步是复杂且难以管理。

    在引擎盖下,引擎实际上是先做它可能做的所有其他事情,然后再做你的网络查询。

    浏览needle npm 文档告诉我,您可以使用替代语法来让 needle 返回一个承诺,然后可以将其包装在一个异步函数中并通过await 进行管理以强制同步行为,这是你所追求的:

    const needle = require('needle');
    const sp = require('serp-parser');
    const queryup = 'watch movies online free';
    const query = encodeURI(queryup);
    let page = 0;
    const pages = 5;
    
    const googler = async function () {
      for (let i = 0; i < pages; i++) {
        try {
          const response = await needle('get', `https://www.google.com/search?q=${query}&start=${page}`);// MY MAIN PROBLEM <<<--- The issue is its adding to the page value but its not effecting it here, why?
          console.log('----- Page number: ' + page / 10 + ' -----');
          const results = await response.body;
          const parser = new sp.GoogleNojsSERP(results);
          const parsed = parser.serp;
          const objarray = parsed.organic;
          for (let i = 0; i < objarray.length; i++) {
            const url = objarray[i].url;
            console.log(url);
          }
        } catch (err) {
          console.error(err);
        }
        page += 10;
      }
    };
    
    googler();
    

    主要区别:

    1. 根据needle 文档,请求方法不是needle 对象上的方法,而是您直接传递给作为函数调用needle 本身的第一个参数。
    2. 当您使用await 管理promise 时,被拒绝的promise 会抛出一个错误,该错误应该被传统的try/catch 块捕获;我在这里做过。不过,如果 needlenode-fetch 类似,它可能基本上不会抛出错误,但这是一种很好的做法。

    我的一个扩展程序自动将您的var 声明更改为let,并且未将let 声明重新分配为const;欢迎您将它们改回来。

    【讨论】:

      【解决方案2】:

      这是一个经典的异步问题。在needle.get() 调用之前(以及for 语句之后)添加另一个console.log(),您将看到发生了什么问题:所有needle.get() 调用都在任何回调之前执行之前你在哪里做page += 10。然后,for 循环完成后,所有的回调都被执行。但这对start=参数产生任何影响已经太晚了。

      解决此问题的一种方法是将这个 for 循环的主体(needle.get() 及其回调)移动到一个单独的函数中。初始化您的变量并调用此函数一次。然后在回调结束时,执行page += 10 并更新您需要的任何其他变量,然后从那里再次调用此函数如果还有更多页面需要加载。如果您已完成所有页面,则不要拨打电话。这种技术不需要for 循环。

      或者,您可以保留当前代码,但将page += 10 回调之后移动,但仍在外部for 循环内。这样,该变量将按照您的预期递增。我不一定建议这样做,因为 Google 可能会对如此迅速地收到 get 请求感到不满,并可能开始阻止您的通话或向您抛出验证码。

      Google 的服务条款是否允许此类抓取可能存在问题,但我会将这个问题留给您和您的法律顾问。

      另外,我会避免在任何地方使用var。请改用constlet,并首选const 而不是let,除非您需要重新分配变量。

      一个提示:在大多数情况下,如果您使用数字 for 循环来迭代数组,那么如果您使用 for..of 循环,代码会更简洁。比如这段代码:

      let parsed = parser.serp
      let objarray = parsed.organic;
      for (var i = 0; i < objarray.length; i++) {
        let url = objarray[i].url
        console.log(url)
      }
      

      可以更简单的写成:

      for (const result of parser.serp.organic) {
        console.log(result.url)
      }
      

      (我知道这只是一些调试代码,但这是一个好习惯。)

      最后,注意缩进并确保缩进嵌套的块或函数。我冒昧地为您添加了一些缩进。

      【讨论】:

        猜你喜欢
        • 2012-10-16
        • 2021-06-07
        • 1970-01-01
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 2013-04-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多