gpt4 book ai didi

node.js - 如何从 Google Cloud Function(Cheerio、Node.js)发出多个 http 请求

转载 作者:太空宇宙 更新时间:2023-11-04 00:02:02 25 4
gpt4 key购买 nike

我的问题:

我正在使用 Cheerio、Node.js 和 Google Cloud Functions 构建一个网络爬虫。

问题是我需要发出多个请求,然后在调用 response.send() 之前将每个请求的数据写入 Firestore 数据库,从而终止该函数。

我的代码需要两个循环:第一个循环使用来 self 的数据库的网址,每个循环发出一个单独的请求。第二个循环是 Cheerio 使用 .each 从 DOM 中抓取多行表数据,并为每一行进行单独的写入。

我尝试过的:

我尝试将每个请求推送到一个 Promise 数组,然后在调用 res.send() 之前等待所有 Promise 用 Promise.all() 解决,但我对 Promise 仍然有点动摇,而不是当然这是正确的方法。 (我已经通过这种方式获得了适用于较小数据集的代码,但仍然不一致。)

我还尝试将每个请求创建为新的 Promise,并使用 async/await 等待 forEach 循环中的每个函数调用,以便为每个请求留出时间并写入完全完成,以便之后我可以调用 res.send(),但是我发现 forEach 不支持 Async/await。

我尝试使用 p-iteration 模块来解决这个问题,但因为它实际上不是 forEach,而是查询上的方法 (doc.forEach()),我认为它不是那样工作的。

这是我的代码。

注意:

如前所述,这并不是我尝试过的所有内容(我删除了我的 promise 尝试),但这应该显示我正在努力实现的目标。

export const getCurrentLogs = functions.https.onRequest((req, response) => {


//First, I make a query from my db to get the urls
// that I want the webscraper to loop through.

const ref = scheduleRef.get()

.then((snapshot) => {

snapshot.docs.forEach((doc) => {

const scheduleGame = doc.data()
const boxScoreUrl = scheduleGame.boxScoreURL

//Inside the forEach I call the request
// as a function with the url passed in

updatePlayerLogs("https://" + boxScoreUrl + "/");


});

})

.catch(err => {
console.log('Error getting schedule', err);
});


function updatePlayerLogs (url){


//Here I'm not sure on how to set these options
// to make sure the request stays open but I have tried
// lots of different things.

const options = {
uri: url,
Connection: 'keep-alive',
transform: function (body) {
return cheerio.load(body);
}
};

request(options)

.then(($) => {


//Below I loop through some table data
// on the dom with cheerio. Every loop
// in here needs to be written to firebase individually.


$('.stats-rows').find('tbody').children('tr').each(function(i, element){


const playerPage = $(element).children('td').eq(0).find('a').attr('href');


const pts = replaceDash($(element).children('td').eq(1).text());
const reb = replaceDash($(element).children('td').eq(2).text());
const ast = replaceDash($(element).children('td').eq(3).text());
const fg = replaceDash($(element).children('td').eq(4).text());
const _3pt = replaceDash($(element).children('td').eq(5).text());
const stl = replaceDash($(element).children('td').eq(9).text());
const blk = replaceDash($(element).children('td').eq(10).text());
const to = replaceDash($(element).children('td').eq(11).text());


const currentLog = {
'pts': + pts,
'reb': + reb,
'ast': + ast,
'fg': fgPer,
'3pt': + _3ptMade,
'stl': + stl,
'blk': + blk,
'to': + to
}

//here is the write
playersRef.doc(playerPage).update({

'currentLog': currentLog

})
.catch(error =>
console.error("Error adding document: ", error + " : " + url)
);
});

})

.catch((err) => {
console.log(err);
});

};

//Here I call response.send() to finish the function.
// I have tried doing this lots of different ways but
// whatever I try the response is being sent before all
// docs are written.

response.send("finished writing logs")

});

我尝试过的所有操作要么会导致超出截止日期的错误(可能是因为我已经研究过配额限制,但我认为我不应该超出),要么是一些无法解释的错误,其中代码未完成执行但显示我的日志中没有任何内容。

请帮忙,在我不理解的这种情况下有没有办法使用 async/await ?有没有办法使用 promise 来使其变得优雅?

非常感谢,

最佳答案

也许看看这样的东西。它使用 Bluebird promisesrequest-promise library

const Promise = require('bluebird');
var rp = require('request-promise');

const urlList = ['http://www.google.com', 'http://example.com']

async function getList() {
await Promise.map(urlList, (url, index, length) => {

return rp(url)
.then((response) => {

console.log(`${'\n\n\n'}${url}:${'\n'}${response}`);
return;
}).catch(async (err) => {
console.log(err);
return;

})


}, {
concurrency: 10
}); //end Promise.map

}

getList();

关于node.js - 如何从 Google Cloud Function(Cheerio、Node.js)发出多个 http 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54209690/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com