javascript - 节点 puppeteer Promise.all 一次查看不同页面时的所有问题
问题描述
所以我对网络抓取相当陌生,并且一直在使用 puppeteer 库来这样做。我设法让大多数事情正常工作,但是当尝试 promise.all 并触发第二个函数以转到两个单独的页面时,它始终是 promise.all 映射中的最后一页,即使在调试器中它也会变为两个它应该已经转到有问题的页面。
触发数据获取的函数类似于下面的代码示例
const fetchSeasonUrls = async () => {
const driver = await configuration.getDriver(baseUrl);
const watchList = await fetchWatchList(driver);
// When the function below is hit the end result looks like example result one below
const watchListSeasons = await Promise.all(
watchList.map(async show => {
await tvSplurgeio.getSeasonData(driver, show);
})
);
// When the function below is hit the end result looks like example result two below
const showOne = await tvSplurgeio.getSeasonData(driver, watchList[0]);
const showTwo = await tvSplurgeio.getSeasonData(driver, watchList[1]);
}
示例结果一
[
[S01, S02, ..., S31],
[S01, S02, ..., S31]
]
示例-结果-二
const showOne = [S01, S02, ..., S10];
const showTwo = [S01, S02, ..., S31];
第二个结果是正确的,因为它导航到正确的显示页面并用它拉回季节数据,但是当它在一个承诺中时,它似乎返回数组中的最后一个东西 x 次。
返回此数据的 puppeteer 代码如下所示。
const tvSplurgeio = {
getSeasonData: async (driver, show) => {
let navigationPromise = driver.page.waitForNavigation();
await driver.page.goto(show.url);
await navigationPromise;
await driver.page.waitForSelector(".sidebar-seasons");
const seasonData = await driver.page.evaluate(() => {
const allSeasons = document.querySelectorAll(
'li[class*="sidebar-season"]'
);
let data = [];
Array.prototype.forEach.call(allSeasons, season => {
Array.prototype.forEach.call(season.children, child => {
const seasonNumber = parseInt(child.innerText.split(" ")[1], 10);
data.push(
seasonNumber < 10 ? `S0${seasonNumber}` : `S${seasonNumber}`
);
});
});
return data;
});
await navigationPromise;
return seasonData;
},
}
我已经尝试了很多东西,从 page.waitFor() 到等待导航承诺,我不太确定这是否只是对 promise.alls 中这个库可以做什么的误解。
克里斯,任何帮助将不胜感激。
解决方案
我怀疑您的问题来自使用Promise.all
. 此外,map
当您想要对数组的元素执行操作,然后返回带有修改的新数组时,更适合使用。
由于您似乎没有使用 from 返回的值map
,因此我建议您尝试forEach
并简单地将 from 返回的每个值推tvSplurgeio.getSeasonData()
送到一个新数组seasonData
中。
const watchList = await fetchWatchList(driver);
const seasonData = [];
watchList.forEach(async show => {
seasonData.push(await tvSplurgeio.getSeasonData(driver, show));
});
推荐阅读
- node.js - How to hide discord token on github
- reactjs - Can you invoke the same useState hook within the same function more than once?
- python-3.x - urllib3 global default timeout value
- r - 以 R 为底的字符向量的子串向量
- elasticsearch - Elasticsearch 无法在一个命令中安装多个插件
- json - Can you decode a child JSON object into its string representation instead of a concrete type?
- python - Does using 'import module_name' statement in a function cause the module to be reloaded?
- mongodb - 无法获取基于 _id 的已排序文档列表
- angularjs - 根据AngularJS中的内容从数据库加载数据时增加textarea的高度
- amazon-s3 - AWS S3 - 插入分桶 ORC 表