Отображение массива, передающего значение в асинхронную функцию Puppeteer, иногда возвращает неправильное значение - PullRequest
0 голосов
/ 20 октября 2018

У меня есть массив, один будет возвращать неверный результат поиска на веб-сайте, другой вернет правильный поиск.

["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.На сайте есть элемент (без класса или идентификатора), который отображается только там, где нет результатов.Для действительных результатов 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;
  }
} 

1 Ответ

0 голосов
/ 20 октября 2018

Существует несколько способов решения вашей проблемы и, точнее, получения результатов.

Чтобы увидеть, есть ли результаты,

!!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, он возвращает данные в противном случае 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 windows (!!) одновременно и, скорее всего, зависнетза счет ресурсов.

Хотя на машине с 16 ГБ оперативной памяти он работал на 100% нормально: D.Вы открываете 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 окон, он должен дождаться полной загрузки страниц, некоторые из них будут иметь проблемы с навигацией, если это не хороший сервер / компьютер или плохой интернет.

На будущеевам нужно изучить Async Await and Queue, если вы хотите создать что-то подобное, которое проходит по 100 ссылкам и возвращает результаты.Если вы передадите 100 элементов, он мгновенно замерзнет, ​​потому что попытается открыть 100 окон Chrome одновременно.Имейте это в виду.

...