Внедрение HTML перед оценкой сценария с кукловодом - PullRequest
0 голосов
/ 31 января 2019

Я хочу внедрить некоторый HTML-код в определенный элемент на странице, используя puppeteer.

HTML-код должен быть введен перед выполнением любого JavaScript.

Есть два способа, которые я мог бы сделатьсделать это:

  1. Вставить HTML, используя page.evaluateOnNewDocument

Эта функция "вызывается после создания документа" , но я не могуполучить доступ к элементам DOM из него.Например:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  page.on('console', consoleObj => console.log(consoleObj.text()));

  await page.evaluateOnNewDocument(
    () => {
      const content = document.querySelector('html');
      console.log(content);
    }
  );

  await page.goto(process.argv[2]);

  await browser.close();
})();

Этот скрипт выводит только новые строки при посещении страницы.

Использование page.setJavaScriptEnabled для предотвращения выполнения JavaScript до того, как я вставлю HTML.Однако, как в соответствии с документами , после запуска я не запускаю javascript.Например:

Мой сценарий выглядит примерно так:

const fs = require('fs');
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  const html = fs.readFileSync('./example.html', 'utf8');

  await page.setJavaScriptEnabled(false)
  await page.goto(process.argv[2]);
  await page.evaluate(
    content => {
      const pageEl = document.querySelector('div.page');
      let node = document.createElement('div');
      node.innerHTML = content;
      pageEl.appendChild(node);
    }, html
  );
  await page.setJavaScriptEnabled(true)

  await browser.close();
})();

В качестве альтернативы, возможно также сделать что-то вроде this , хотя это выглядит чрезмерносложный для того, что является довольно простым запросом.

Есть ли более простой способ сделать это, что я пропускаю?

Приветствия

1 Ответ

0 голосов
/ 04 февраля 2019

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

Тем не менее, я остановился на решении, предложенном Аслушниковым здесь .

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

Я сделал простую функцию для выполнения XHR:

const requestPage = async (url) => {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.setRequestHeader('Ignore-Intercept', 'Value');
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300) {
        const response = {};
        xhr.getAllResponseHeaders()
          .trim()
          .split(/[\r\n]+/)
          .map(value => value.split(/: /))
          .forEach(keyValue => {
              response[keyValue[0].trim()] = keyValue[1].trim();
          });
        resolve({ ...response, body: xhr.response });
      } else {
        reject({
            status: this.status,
            statusText: xhr.statusText
        });
      }
    };
    xhr.onerror = function () {
      reject({
          status: this.status,
          statusText: xhr.statusText
      });
    };
    xhr.send();
  });
};

Затем я открыл эту функцию на странице.

Затем я использовал эту функцию для выполнения XHR вместо разрешения запроса и использовал результат этого в качестве ответа на запрос.

await page.setRequestInterception(true);
page.on('request', async (request) => {
  if (
    request.url() === url
    && (
      typeof request.headers()['access-control-request-headers'] === 'undefined'
      || !request.headers()['access-control-request-headers'].match(/ignore-intercept/gi)
    ) && typeof request.headers()['ignore-intercept'] === 'undefined'
  ) {
    const response = await page.evaluate(`requestPage('${url}')`);
    response.body += "hello";
    request.respond(response);
  } else {
    request.continue();
  }
});

await page.goto(`data:text/html,<iframe style='width:100%; height:100%' src=${url}></iframe>`);

К сожалению, использование page.evaluate казалось невозможным, если нужная страница не была в фрейме.(отсюда await page.goto(`data:text/html....

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