簡體   English   中英

映射數組傳遞值到異步Puppeteer函數有時會返回不正確的值

[英]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

例如,

  • 搜索中使用的ajax請求包含/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 ]

編輯2:

如果您在該數組中傳遞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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM