Как я могу перейти к следующей итерации, если элемент DOM отсутствует на странице? - PullRequest
1 голос
/ 06 мая 2019

Я бы хотел проверить несколько подстраниц на странице с кукловодом. Веб-страница имеет некоторую защиту от ботов. У меня есть URL-адреса в массиве, и я перебираю этот массив.

Я застрял в том, как мне следует переписать свой код, потому что я столкнулся с несколькими проблемами: из-за защиты бота страница отправляет браузеру несколько статусов «подделка загружена», прежде чем она действительно загружает реальный контент. Поэтому из-за этого я думаю, что мне нужно подождать некоторых элементов DOM.

await page.waitForSelector('div.site__content');

чтобы быть уверенным, что контент загружен. (await page.evaluate не работает из-за защиты ботов, он срабатывает по первому признаку «подделка загружена»).

Но вот еще одна проблема: если страница загружается неправильно (например, из-за тайм-аута соединения), я получаю необработанную ошибку отклонения обещания, и итерация останавливается, выполнение программы останавливается.

Моя цель заключается в том, чтобы при загрузке страницы возникла какая-либо ошибка, пропустите текущую итерацию и перейдите к следующей без сбоя программы. Но я должен держать

await page.waitForSelector

часть тоже. Как мне этого добиться?

(async function filterIds() {
  let filteredIds = ['url1', 'url2', '...', 'url200'];
  const browser = await puppeteer.launch({ headless: false });
  const context = await browser.createIncognitoBrowserContext();
  const page = await context.newPage();
  await tuneUserAgent(page);
  for (let id in filteredIds) {
    let errorPage = null;
    let url = filteredIds[id];
    await page.goto(url, { waitUntil: 'load', timeout: 120000 });
    await page.waitForSelector('div.site__content'); // to be sure that the content has been loaded
    errorPage = await page.evaluate(() => {
      return document.querySelector('div.errorpage');
    });
    if (errorPage != null || errorPage === undefined) {
      continue;
    }
    await page.waitForSelector('div.dialog');
    let noGallery = await page.evaluate(() => {
      return document.querySelector('div[class="is-not-photo-uploaded-text"]');
    });
    if (noGallery != null || noGallery === undefined) {
      openOrNot = 5;
    }
    if (openOrNot < 4) {
      await openGallery(page);
    }
    let html = await page.content();
    await fs.writeFile(`./saved_items/${filteredIds[id].substring(filteredIds[id].lastIndexOf('/') + 1)}.html`, html, function (err) {
      if (err) throw err;
    });
    await page.waitFor(400);
  }
  await browser.close();
})();

1 Ответ

2 голосов
/ 07 мая 2019

«Необработанная ошибка отклонения обещания» выдается, когда обещание отклонено и не перехвачено.Это неявный случай, если исключение выдается внутри блока асинхронного кода, как в вашем случае.

Чтобы перехватить выброшенное исключение, вы можете просто использовать блок try..catch внутри цикла.

Пример кода

for (let id in filteredIds) {
  try {
    // your code
  } catch (err) {
    console.log(`Iteration for ${id} failed with error: ${err.message}`);
  }
}

Этот код должен перехватывать все ошибки, вызванные вашим кодом, за исключением if (err) throw err; внутри fs.writeFile, поскольку этот обратный вызов вызывается асинхронно и, следовательно,выполняется за пределами вашего try..catch блока.Но вы можете просто использовать новый fs.promises.writeFile, чтобы даже отловить эту ошибку.

В случае возникновения ошибки будет вызвана часть скрипта catch (err) { ... }, которая регистрирует ошибкусообщение и id, для которого произошла ошибка.Поскольку сценарий больше не падает, цикл продолжится со следующей итерации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...