Кукольник: скриншот ленивых картинок не работает - PullRequest
0 голосов
/ 04 апреля 2019

Я, кажется, не могу сделать снимок экрана с https://today.line.me/HK/pc успешно.

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

function wait (ms) {
 return new Promise(resolve => setTimeout(() => resolve(), ms));
}

const puppeteer = require('puppeteer');

async function run() {
let browser = await puppeteer.launch({headless: false});
let page = await browser.newPage();
await page.goto('https://today.line.me/HK/pc', {waitUntil: 'load'});
//https://today.line.me/HK/pc
// Get the height of the rendered page
  const bodyHandle = await page.$('body');
  const { height } = await bodyHandle.boundingBox();
  await bodyHandle.dispose();

  // Scroll one viewport at a time, pausing to let content load
  const viewportHeight = page.viewport().height+200;
  let viewportIncr = 0;
  while (viewportIncr + viewportHeight < height) {
    await page.evaluate(_viewportHeight => {
      window.scrollBy(0, _viewportHeight);
    }, viewportHeight);
    await wait(4000);
    viewportIncr = viewportIncr + viewportHeight;
  }

  // Scroll back to top
  await page.evaluate(_ => {
    window.scrollTo(0, 0);

  });

 // Some extra delay to let images load
 await wait(2000);

await page.setViewport({ width: 1366, height: 768});
await page.screenshot({ path: './image.png', fullPage: true });
}

run();

Puppeteer Line Screenshot Fails

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Я решил эту проблему, изменив логику того, как я могу прокручивать страницу и ждать задержки.

0 голосов
/ 01 июля 2019

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

Я знаю это, потому что я запускаю небольшой проект «Снимок как услуга» (https://getscreenshot.rasterwise.com/)), и мне пришлось рассматривать множество случаев отдельно. Это большая задача этого проекта, поскольку, кажется, всегда есть что-то новое, что необходимо быть обращенным к новым библиотекам и методам пользовательского интерфейса, используемым каждый день.

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

//Scroll and Wait Strategy

function waitFor (ms) {
  return new Promise(resolve => setTimeout(() => resolve(), ms));
}

async function capturePage(browser, url) {
  // Load the page that you're trying to screenshot.
  const page = await browser.newPage();
  await page.goto(url, {waitUntil: 'load'}); // Wait until networkidle2 could work better.


  // Set the viewport before scrolling
  await page.setViewport({ width: 1366, height: 768});

  // Get the height of the page after navigating to it.
  // This strategy to calculate height doesn't work always though. 
  const bodyHandle = await page.$('body');
  const { height } = await bodyHandle.boundingBox();
  await bodyHandle.dispose();

  // Scroll viewport by viewport, allow the content to load
  const calculatedVh = page.viewport().height;
  let vhIncrease = 0;
  while (vhIncrease + calculatedVh < height) {
    // Here we pass the calculated viewport height to the context
    // of the page and we scroll by that amount
    await page.evaluate(_calculatedVh => {
      window.scrollBy(0, _calculatedVh);
    }, calculatedVh);
    await waitFor(300);
    vhIncrease = vhIncrease + calculatedVh;
  }

  // Setting the viewport to the full height might reveal extra elements
  await page.setViewport({ width: 1366, height: calculatedVh});

  // Wait for a little bit more
  await waitFor(1000);

  // Scroll back to the top of the page by using evaluate again.
  await page.evaluate(_ => {
    window.scrollTo(0, 0);
  });

  return await page.screenshot({type: 'png'});
}

Вот некоторые ключевые отличия: - Вы хотите установить область просмотра с самого начала и работать с этим фиксированным окном просмотра. - Вы можете изменить время ожидания и ввести произвольные ожидания для эксперимента. Иногда это приводит к раскрытию элементов, которые висят за сетевыми событиями. - Изменение области просмотра на полную высоту страницы также может показать элементы, как если бы вы прокручивали. Вы можете проверить это в реальном браузере, используя вертикальный монитор. Однако обязательно вернитесь к исходной высоте области просмотра, поскольку область просмотра также влияет на предполагаемый рендеринг.

Здесь нужно понять одну вещь: ожидание в одиночку не обязательно приведет к загрузке ленивых активов. Прокрутка по высоте документа позволяет в окне просмотра отображать те элементы, которые должны находиться в окне просмотра для загрузки.

Еще одна оговорка: иногда вам нужно ждать относительно долгое время для загрузки актива, поэтому в приведенном выше примере вам может потребоваться поэкспериментировать с количеством времени, которое вы ждете после каждой прокрутки. Кроме того, как я упоминал, произвольные ожидания в общем исполнении иногда влияют на загрузку актива или нет.

Как правило, при использовании Puppeteer для снимков экрана вы хотите убедиться, что ваша логика напоминает реальное поведение пользователя. Ваша цель - воспроизвести сценарии рендеринга, как если бы кто-то запускал Chrome на своем компьютере и переходил на этот веб-сайт.

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