NODE JS - 请求 npm - 操纵 url 主体
NODE JS - request npm - manipulate url body
我正在使用节点 js(第一次)在服务器端(自己)项目上工作,我 运行 遇到了一些困难。
我的目标如下:
第一部分 - 我在我的服务器中使用“/uploads/processData”URL 从用户请求中获取 URL(s)。
现在我想访问用户请求 URL(s) 并获取他们的 HTML(s) 文件,为此我正在使用 "request" npm 包(下面的代码)。
第二部分 - 我想访问从请求包(从第一部分)返回的正文,所以我使用 cheerio npm 包来这样做。
现在我的问题 - 假设我正在尝试获取 url 的正文:
由于某些我无法理解的原因(可能是因为缺乏网络开发知识),我总是得到与我查看上述页面时看到的相同的主体(link) 使用 F12,以及我的第一部分代码。因此,有时我的 cheerio 提取(第二部分)会按我的预期工作,有时却不会(因为 full/original HTML 文件中的某些元素丢失了)。起初我以为它可能是缓存的东西,所以我添加了一个中间件来设置 "nocache" 标志。
我在这里错过了什么?我尝试操作的方式是否错误?有什么方法可以确保我每次都得到相同的 full/original HTML 吗?
到目前为止,这是我的代码 -
无缓存中间件
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);
});
我将代码更改为上面的代码,数据提取似乎更加频繁。谁能解释为什么提取有时仍然不起作用?
我尝试 return 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) 在所有请求发生后运行
有几种方法可以解决这个问题,一种是使用优秀的 async library。
希望你能通过这个例子得到它的要点。
var array = [1,2,3]
function asyncRequest(input, callback){
//Do your fetch request here and call callback when done
setTimeout(callback, 10); //using setTiemout as an example
}
async.each(array, asyncRequest, (err) => {
if(err){
throw err;
}
console.log("All Finished");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/async/2.6.1/async.min.js"></script>
在查看了 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);
}
我正在使用节点 js(第一次)在服务器端(自己)项目上工作,我 运行 遇到了一些困难。
我的目标如下:
第一部分 - 我在我的服务器中使用“/uploads/processData”URL 从用户请求中获取 URL(s)。
现在我想访问用户请求 URL(s) 并获取他们的 HTML(s) 文件,为此我正在使用 "request" npm 包(下面的代码)。
第二部分 - 我想访问从请求包(从第一部分)返回的正文,所以我使用 cheerio npm 包来这样做。
现在我的问题 - 假设我正在尝试获取 url 的正文:
由于某些我无法理解的原因(可能是因为缺乏网络开发知识),我总是得到与我查看上述页面时看到的相同的主体(link) 使用 F12,以及我的第一部分代码。因此,有时我的 cheerio 提取(第二部分)会按我的预期工作,有时却不会(因为 full/original HTML 文件中的某些元素丢失了)。起初我以为它可能是缓存的东西,所以我添加了一个中间件来设置 "nocache" 标志。
我在这里错过了什么?我尝试操作的方式是否错误?有什么方法可以确保我每次都得到相同的 full/original HTML 吗?
到目前为止,这是我的代码 - 无缓存中间件
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);
});
我将代码更改为上面的代码,数据提取似乎更加频繁。谁能解释为什么提取有时仍然不起作用? 我尝试 return 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) 在所有请求发生后运行
有几种方法可以解决这个问题,一种是使用优秀的 async library。
希望你能通过这个例子得到它的要点。
var array = [1,2,3]
function asyncRequest(input, callback){
//Do your fetch request here and call callback when done
setTimeout(callback, 10); //using setTiemout as an example
}
async.each(array, asyncRequest, (err) => {
if(err){
throw err;
}
console.log("All Finished");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/async/2.6.1/async.min.js"></script>
在查看了 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);
}