Node.js 节点JS-请求npm-操纵url正文

Node.js 节点JS-请求npm-操纵url正文,node.js,cheerio,npm-request,Node.js,Cheerio,Npm Request,我正在使用NodeJS进行服务器端(self)项目(这是第一次),遇到了一些困难 我的目标如下: 第一部分-Im在我的服务器中使用“/uploads/processData”URL从用户请求中获取URL 现在我想访问用户请求URL并获取他们的HTML文件,为此我使用“请求”npm包(下面的代码) 第二部分-我希望访问从请求包(第一部分)返回的主体,因此我使用cheerio npm包来实现这一点 现在我的问题是——假设我正在尝试获取url的主体: 由于某些我无法理解的原因(可能是因为缺乏网络开发

我正在使用NodeJS进行服务器端(self)项目(这是第一次),遇到了一些困难

我的目标如下:

第一部分-Im在我的服务器中使用“/uploads/processData”URL从用户请求中获取URL

现在我想访问用户请求URL并获取他们的HTML文件,为此我使用“请求”npm包(下面的代码)

第二部分-我希望访问从请求包(第一部分)返回的主体,因此我使用cheerio npm包来实现这一点

现在我的问题是——假设我正在尝试获取url的主体:

由于某些我无法理解的原因(可能是因为缺乏网络开发方面的知识),我并不总是能得到与我使用F12查看上面页面(链接)时看到的相同的正文,以及我的第一部分代码。因此,有时我的cheerio提取(第二部分)会像我预期的那样工作,有时则不会(因为完整/原始HTML文件中的某些元素丢失)。起初我认为这可能是缓存,所以我添加了一个中间件来设置“nocache”标志

我错过了什么?我尝试操作的方式是否错误?有没有办法确保我每次都得到相同的完整/原始HTML

这是到目前为止我的代码- nocache中间件

function nocache(req, res, next) {
res.header("Cache-Control", "private, no-cache, no-store, must-revalidate");
  res.header("Expires", "-1");
  res.header("Pragma", "no-cache");
  next();
}
编辑

uploadRoutes.post("/processGoogleSearchData", nocache, (req, res) => {
  //Assuming getting in req.body the google result JSON as "googleSearchResult"
  var itemsArr = [];
  var linksArr = [];
  var bodysArr = [];
  itemsArr = req.body.googleSearchResult.items;
  if (itemsArr.length === 0) {
    //return appropriate message
    return res.status(400).send({ message: "No data sent to server" });
  }
  var linksArr = itemsArr.map(item => item.link);

  //Get the needed info from every link
  linksArr.forEach(link => {
    request(link, (err, response, body) => {
      if (!err && response.statusCode === 200) {
        var $ = cheerio.load(body);
        var tr = $(".a-lineitem").children();
        var priceTd = tr.find(".a-span12");
        var priceSpan = priceTd.find("#priceblock_ourprice");
        console.log(priceSpan.text());
        //when trying to build array of bodys the extraction doesnt work at all
        bodysArr.push(body);
      }
    });
  });
  res.send(bodysArr);
});
我将代码改为上面的代码,看起来数据提取工作更频繁。有人能解释为什么提取有时仍然不起作用吗? 出于debbug的目的,我尝试返回bodysArr,但当我这样做时,提取根本不起作用,而且我的路径响应总是空数组,这是为什么?

问题在于:

res.send(bodysArr);
在调用之后直接执行

linksArr.forEach(link => {
回调

(err, response, body) => {
  if (!err && response.statusCode === 200) {
    var $ = cheerio.load(body);
    var tr = $(".a-lineitem").children();
    var priceTd = tr.find(".a-span12");
    var priceSpan = priceTd.find("#priceblock_ourprice");
    console.log(priceSpan.text());
    //when trying to build array of bodys the extraction doesnt work at all
    bodysArr.push(body);
  }
还不能保证已经开火了。您需要的是确保res.send(bodysArr)在所有请求发生后运行

有几种方法可以解决这个问题,其中一种是使用优秀的

希望您能通过这个示例了解它的要点

var数组=[1,2,3]
函数asyncRequest(输入、回调){
//在此处执行提取请求,完成后调用回调
setTimeout(callback,10);//以setTiemout为例
}
async.each(数组、asyncRequest,(err)=>{
如果(错误){
犯错误;
}
控制台日志(“全部完成”);
});

在查看了Sudsy解释之后,我遇到了异步方法的循环

在处理此主题时,我无法找出以下代码的错误:

这很好用-因此我最终使用了它

async function getItemsInfo(itemsArr) {
  return itemsArr.map(async item => {
    try {
      var body = await axios(item.link);
      var $ = await cheerio.load(body.data);
      var tr = await $(".a-lineitem").children();
      var priceTd = await tr.find(".a-span12");
      var priceSpan = await priceTd.find("#priceblock_ourprice");
      return priceSpan.text();
    } catch (err) {
      return err.message;
    }
  });
}

getItemsInfo(linksArr)
    .then(res => Promise.all(res))
    .then(res => console.log(res))
    .catch(err => console.error(err));
有人能给我解释一下以下代码有什么问题吗?

async function getItemsInfo(itemsArr) {
  await Promise.all(
    itemsArr.map(async item => {
      try {
        var body = await axios(item.link);
        var $ = await cheerio.load(body.data);
        var tr = await $(".a-lineitem").children();
        var priceTd = await tr.find(".a-span12");
        var priceSpan = await priceTd.find("#priceblock_ourprice");
        return priceSpan.text();
      } catch (err) {
        throw err.message;
      }
    })
  )
    .then(resulst => {
      return results;
    })
    .catch(err => {
      throw err.message;
    });
}
//the caller function
try {
    getItemsInfo(linksArr).then(results => {
      res.status(200).send(results);
    });
  } catch (err) {
    res.status(400).send(err.message);
  }

async function getItemsInfo(itemsArr) {
  const promises = itemsArr.map(async item => {
    try {
      var body = await axios(item.link);
      var $ = await cheerio.load(body.data);
      var tr = await $(".a-lineitem").children();
      var priceTd = await tr.find(".a-span12");
      var priceSpan = await priceTd.find("#priceblock_ourprice");
      return priceSpan.text();
    } catch (err) {
      return err.message;
    }
  });

  var results = await Promise.all(promises)
    .then(results => {
      return results;
    })
    .catch(err => {
      return err.message;
    });
  }

    //the caller function
    try {
            getItemsInfo(linksArr).then(results => {
              res.status(200).send(results);
            });
          } catch (err) {
            res.status(400).send(err.message);
          }

谢谢@Sudsy我现在明白我的问题了。