Как настроить Puppeteer для правильного отображения внешних JS-страниц? Работает только для URL-адресов Localhost

#node.js #puppeteer #google-chrome-headless #serverside-javascript

#node.js #puppeteer #google-chrome-безголовый #серверная часть-javascript

Вопрос:

Я пытаюсь настроить рендеринг на стороне сервера для внешних страниц Javascript. Я использую Puppeteer для этой цели, и когда я предоставляю любой внешний URL (не страницы локального хостинга), Puppeteer извлекает только исходный код URL-адреса (то, что вы можете увидеть в режиме просмотра исходного кода запрашиваемой страницы), без отображения всего DOM. Когда я пытаюсь SSR любой URL-адрес страницы localhost Javascript (страница, сгенерированная тем же узловым js-сервером на моем локальном хосте) — все работает нормально.

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

Мне удалось настроить puppeteer со всеми зависимостями от моего локального хостинга, как показано ниже:

В настоящее время переменная ‘html’ возвращает только исходный код выбранного URL-адреса, мне нужно получить полностью отображенный DOM запрошенного URL-адреса.

Код в server.js

 var puppeteer = require('puppeteer');

async function ssr(url) {
  console.info('rendering the page in ssr mode');
  const browser = await puppeteer.launch({headless: true});
  const page = await browser.newPage();

  try {
    await page.goto(url, {waitUntil: 'domcontentloaded'});
  } catch (err) {
    console.error(err);
    throw new Error('page.goto/waitForSelector timed out.');
  }

  const html = await page.content();
  await browser.close();
  return {html};
}

module.exports = ssr;
  

Код в app.js

 var err = require('http-errors');
var express = require('express');
var path = require('path');
var ssr = require('./ssr.js');

var app = express();

app.listen(3000, function(){ console.info('Server listening on port '); });

app.use('/index/', async(req, res) => {
  const { html } = await ssr(`www.example.com`);
  return res.send(html);
});
  

Ответ №1:

Проблема, вероятно, в том, что вы не даете странице достаточно времени для отображения содержимого DOM. {waitUntil: 'domcontentloaded'} будет ожидать только события DOMContentLoaded, а не каких-либо AJAX-запросов или модификаций DOM.

Попробуйте вместо этого использовать 'networkidle0' or 'load' в качестве waitUntil значения функции page.goto.goto.goto.

Если это не сработает, у вас есть два варианта:

  • Дайте странице фиксированное количество времени для отображения страницы с помощью await page.waitFor(1000)
  • Используйте await page.waitForSelector(/* ... */) , чтобы дождаться загрузки определенного селектора перед вызовом page.content() . Таким образом, вы можете убедиться, что интересующие вас части документа загружены.

Комментарии:

1. На самом деле я пытался использовать параметры, описанные в официальной документации Google: ‘networkidle0’, ‘networkidle2’ и page.waitForSelector (…) перед публикацией моего публичного вопроса, но результат был тот же — Puppeteer вернул только исходный HTML-код URL-адреса (как если бы я проверил страницу в режиме просмотра исходного кода). Все это идеально работает только для страниц, которые генерируются NodeJS на локальном хостинге. Даже не знаю, что проверять.

2. Привет, Томас! К сожалению, это не так… Может ли это быть из-за localhost (но, я думаю, для этого нет причин). Люди с форума разработчиков Chrome не отвечают. Нет, идея…

3. Я получаю 404 отчета в терминале для всех связанных скриптов и изображений…

Ответ №2:

попробуйте

 const html = 'what ever you selector is but since you want the html just type in "html"'; 

let gg = await page.evaluate((sel) => {
        let element = document.querySelector(sel);
        console.log ('got Boom');
        return element? element.innerHTML: null;
    }, html);


    console.log (gg);

  

Комментарии:

1. Привет, Раках Хабаб!

2. Спасибо за ваш ответ! Я пока не эксперт, поэтому не могли бы вы, пожалуйста, уточнить, куда именно мне следует интегрировать предоставленный вами фрагмент кода?

3. Внутри вашего оператора try

4. Спасибо, Рак. Я попробовал — снова в терминал возвращается только исходный код запрошенной страницы, сборка DOM с помощью JS не отображается. Не знаю, что тогда делать…

5. Я не знаю, какой результат вы хотите. Например, вы хотите, чтобы текст заголовка в данном случае был «Example» ИЛИ вы хотите, чтобы он был таким «<h> Example<h>»