Кукольник exposeFunction, который использует несериализуемый аргумент - PullRequest
0 голосов
/ 26 сентября 2018

Я пытаюсь использовать стороннюю библиотеку, которая выполняет сложный анализ DOM:

/** 
 *  // Simplified for this example
 *  module.exports.parse = (document) => {return document.title; }
 */

const { parse } = require('./parse.js');

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

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://stackoverflow.com', { waitUntil: ['domcontentloaded'] });
await page.exposeFunction('parse', (document) => {
    return parse(document);
});

await page.evaluate(() => {
    return window.parse(window.document);
});

Я получаю сообщение об ошибке:

Ошибка оценки: TypeError: Преобразование круговой структуры в JSON \ n в JSON.stringify () \ n в окне (анонимная функция) ( puppeteer_evaluation_script :13:22) \ n at puppeteer_evaluation_script : 3: 31

В примере документации передается строка (которую можно сериализовать).Есть ли какой-нибудь известный способ оценки методов node.js, которые принимают window или document в качестве аргументов?

1 Ответ

0 голосов
/ 27 сентября 2018

Этот метод, описанный ниже, немного отличается, поэтому используйте его с осторожностью.

Мы можем перенести скрипт в браузер вместо того, чтобы переносить dom в контекст узла.Это возможно с мощью webpack или browserify.Также, таким образом, нам не нужно сериализовать циклические переменные.

Вот минимальная конфигурация веб-пакета.

const path = require("path");

module.exports = {
  entry: "./browser/src.js",

  output: {
    path: path.resolve("browser"),
    filename: "dist.js",
    libraryTarget: "global"
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        use: "babel-loader"
      }
    ]
  }
};

Мы поместим скрипт браузера в папку browser/src.js.Затем, когда мы запустим webpack, он сгенерирует browser/dist.js, который мы можем добавить в браузер.

Наконец, я могу назвать его одним из следующих способов:

await page.addScriptTag({path: "./browser/dist.js"});
await page.evaluate(fs.readFileSync("./browser/dist.js", 'utf8'));

Он отлично работает, пока мы не используем какой-либо собственный двоичный файл, который невозможно объединить.

Для простоты, вот другие файлы,

// browser/src.js
module.exports.parse = window => {
  return window.location.href;
};

// index.js
const fs = require("fs");
const puppeteer = require("puppeteer");
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.evaluate(fs.readFileSync("./browser/dist.js", 'utf8'));
  const data = await page.evaluate(() => {
    return parse(window);
  });

  console.log({ data });
})();

// The result:
{ data: 'about:blank' }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...