[英]Mapping over array using Async/Await with Puppeteer to return result
[英]Mapping over array passing value to async Puppeteer function will sometimes return incorrect value
我有一個數組,一個將在網站上返回無效的搜索結果,另一個將返回有效的搜索。
["sakdjlkasjda", "Assassin's Creed Origins"]
然后,我在數組上映射並將值傳遞給異步函數
const cex = games.map((game) => cexSearch(game));
return Promise.all(cex)
.then(function(g) {
console.log(g);
res.send(g);
});
在異步功能中,我創建一個Puppeteer實例,導航到URL。 該網站有一個元素(沒有類或ID),僅在沒有結果的地方顯示。 對於有效結果, noRecordsDisplay
應該等於none
,在沒有有效結果的情況下, noRecordsDisplay
應該等於""
。 但是,有幾次我注意到,對於應該無效的搜索, noRecordsDisplay
等於none
,所以不確定在哪里出錯了,它在大多數情況下都有效,但並非始終如此? 任何幫助將不勝感激。
async function cexSearch(game) {
const url = 'https://uk.webuy.com/search?stext=' + game;
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36');
await page.goto(url, {
timeout: 3000000
});
const content = '.content-area';
await page.waitForSelector(content);
await page.waitForSelector('.content-area > div:not(.searchRcrd)');
const noRecordsDisplay = await page.evaluate(() => document.querySelector('.content-area > div:not(.searchRcrd)').style.display);
console.log("display = " + noRecordsDisplay);
if (noRecordsDisplay === "") {
return "No Search Results";
} else {
//When there is an invalid search it sometimes reaches here and .searchRcrd does not exist so it timesout
const selector = '.searchRcrd';
await page.waitForSelector(selector);
// DO logic
await browser.close();
return records;
}
}
有多種解決問題的方法,可以更精確地獲得結果。
要查看是否有結果,
!!document.querySelector('.searchRcrd') // => Returns true if results are available
用法:
const noRecordsDisplay = await page.evaluate(() => !!document.querySelector('.searchRcrd'));
另一種方法是用waitForResponse
代替waitForSelector
。
例如,
/v3/boxes?q=
response.data
,它返回data,否則返回null。 用法:
const finalResponse = await page.waitForResponse(response => response.url().includes('/v3/boxes?q=') && response.status() === 200);
const data = (await finalResponse.json()).data;
您的代碼不會等到頁面完全加載。 要等待頁面完全加載,應使用waitUntil
選項。
這是完整的工作代碼。
const puppeteer = require("puppeteer");
const games = ["Does not Exist", "Assassin's Creed Origins"];
const cex = games.map(game => cexSearch(game));
Promise.all(cex).then(function(g) {
console.log(g);
});
async function cexSearch(game) {
const url = "https://uk.webuy.com/search?stext=" + game;
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto(url, { waitUntil: "networkidle0" }); // <-- wait for page to load properly
await page.waitForSelector(".content-area > div:not(.searchRcrd)");
const noRecordsDisplay = await page.evaluate(
() => !!document.querySelector(".searchRcrd")
);
if (!noRecordsDisplay) {
console.log(game, ">> No Search Results");
await browser.close();
return false;
}
console.log(game, ">> Result Exists");
await browser.close();
return true;
}
結果:
➜ node app.js
No Search Results
Result Exists
[ false, true ]
如果您在該數組中傳遞6個元素 ,則該應用將嘗試一次打開6個實例/ chrome窗口(!!) ,並且很可能由於資源而掛起。
在:16D內存的機器上,它對我來說100%很好。 您一次打開6頁,這是一個完全不同的問題。 請參閱此處以了解並發性答案。
更多測試:
Quantam Break >> No Search Results
FIFA 19 >> Result Exists
asdhsuah >> No Search Results
asucinuasu >> No Search Results
No Man's Sky >> Result Exists
Overcooked 2 >> Result Exists
[ false, true, true, false, true, false ]
查看最終結果與控制台日志的順序如何不同。 這是由於異步特性。
您必須查看整體圖片。 如果您傳遞6個元素,它將打開6個窗口,它必須等待頁面完全加載,如果服務器/計算機不是很好,或者互聯網不佳,某些頁面就會出現導航問題。
為了以后的嘗試,如果要構建通過100個鏈接並返回結果的對象,則需要學習Async Await和Queue。 如果您傳遞100個元素,它將立即凍結,因為它將嘗試立即打開100個chrome窗口。 記住這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.