Headless Chrome (Puppeteer) - как получить доступ к элементу узла документа?

Я использую phantomJs для анализа некоторого контента и получения от него информации (максимальный размер изображения на страницу, например) и т. д. Я решил перейти на кукловод. И я столкнулся с проблемой - в моих функциях, которые выполнялись на phantomJs, они работали с элементом узла документа. Итак, в кукольнике, как я понял, невозможно вернуть элемент node из page.evaluate и других функций. Итак, есть ли другой способ решить эту проблему? Или, может быть, мне нужно использовать другую библиотеку? Спасибо!


person Brissy    schedule 14.01.2018    source источник
comment
Не знаете, какие проблемы у вас возникают с узлом?   -  person guest271314    schedule 15.01.2018
comment
Сделайте github.com/GoogleChrome/puppeteer/blob/master / docs / и github.com/ GoogleChrome / puppeteer / blob / master / docs / не возвращает ожидаемый результат?   -  person guest271314    schedule 15.01.2018
comment
Нет, он всегда возвращает сериализованный результат, поэтому любые структуры, подобные массиву, будут похожи на {}   -  person Brissy    schedule 15.01.2018
comment
Вы пробовали использовать флаг --dump-dom и разбирать строку HTML?   -  person guest271314    schedule 15.01.2018
comment
Он напечатает document.body.innerHTML, не так ли? Мне нужен именно элемент узла документа, чтобы я мог выбирать контент и управлять им.   -  person Brissy    schedule 15.01.2018
comment
Нашел оптимальное решение. Я импортировал свои модули с помощью page.addScriptTag . Это позволило мне использовать их на странице. Существует альтернативный способ добиться этого, используя страницу . .exposeFunction, но мне это показалось менее удобным.   -  person Brissy    schedule 17.12.2018


Ответы (2)


При использовании Puppeteer необходимо учитывать две среды:

  1. Среда Node.js
  2. Страница DOM Environment

Среда Node.js построена на движке Google Chrome V8 JavaScript.

Chrome V8 описывает свое отношение к модели DOM:

JavaScript чаще всего используется для создания сценариев на стороне клиента в браузере, например, для управления объектами объектной модели документа (DOM). Однако модель DOM обычно предоставляется не движком JavaScript, а браузером. То же самое верно и для V8 - Google Chrome предоставляет DOM. Однако V8 предоставляет все типы данных, операторы, объекты и функции, указанные в стандарте ECMA.

Другими словами, DOM по умолчанию не предоставляется Node.js.

Это означает, что Node.js не может самостоятельно интерпретировать элементы DOM.

Вот здесь и появляется Кукловод.

Функция Puppeteer page.evaluate() позволяет оценивать выражение в текущем контексте DOM страницы с использованием Chrome или Chromium.

В документации Puppeteer описано, что происходит, когда вы попытаться вернуть несериализуемое значение, например элемент DOM:

Если функция, переданная в page.evaluate, возвращает несериализуемое значение, тогда page.evaluate преобразуется в undefined.

Опять же, это потому, что Node.js не знает, как интерпретировать элементы DOM без посторонней помощи.

В результате Puppeteer реализовал _5 _ класс, представляющий внутристраничный элемент DOM.

Вы можете использовать elementHandle.$(), _ 7_ или _ 8_, чтобы вернуть ElementHandles обратно в Node.js.

Класс ElementHandle является сериализуемым, поэтому его можно правильно интерпретировать в среде Node.js.

Следовательно, если вам нужно напрямую управлять элементом, вы можете сделать это внутри page.evaluate(). Если вам нужно получить доступ к представлению элемента, используйте page.$() или одну из связанных с ним функций.

person Grant Miller    schedule 14.08.2018

В ответе Гранта Миллера обсуждаются некоторые методы и даются ссылки на документацию, но нет кода. Вот демонстрационный код, который показывает:

  • Получение ElementHandle для тела документа путем вызова метода page.$.
  • Добавление класса в тело путем вызова его classList.add метода в контексте вызова page.evaluate метода.
  • Печать PDF-файла веб-страницы example.com с оранжевым фоном, чтобы показать, что класс был добавлен.

Код:

const parameters = {
    "launchParameters": { "args": [] },
    "gotoURI": "https://example.com",
    "marginSpecification": {"top": "0", "right": "0", "bottom": "0", "left": "0"},
    "pdfPath": "example.pdf",
    "styleTag":
        'body.orangey, body.orangey div {background-color: orange;}',
    "addBodyClass": "orangey",
    "footerTemplate": "<div></div>",
    "headerTemplate": "<div></div>",
};
console.log("Node version: " + process.version);

const puppeteer = require("puppeteer");

(async () => {
    console.log("await puppeteer.launch");
    const browser = await puppeteer.launch(parameters.launchParameters);

    console.log("await browser.newPage");
    const page = await browser.newPage();

    console.log("await page.goto");
    await page.goto(parameters.gotoURI, {waitUntil: 'networkidle2'});

    console.log("await page.addStyleTag");
    await page.addStyleTag({
        "content": parameters.styleTag
    });

    if (!!parameters.addBodyClass) {
        console.log("await page dollar.")
        const bodyHandle = await page.$('body');
        console.log("Body handle", (!!bodyHandle) ? "OK." : "no.");
        console.log(`await add class "${parameters.addBodyClass}"`);
        await page.evaluate(
            (body, addBodyClass) => body.classList.add(addBodyClass),
            bodyHandle, parameters.addBodyClass)
        .catch(error => console.log(error));
        console.log("await body handle dispose.");
        await bodyHandle.dispose();
    }

    const pdfOptions = {
        path: parameters.pdfPath,
        format: 'A4',
        margin: parameters.marginSpecification,
        displayHeaderFooter: true,
        printBackground: true,
        footerTemplate: parameters.footerTemplate,
        headerTemplate: parameters.headerTemplate
    };

    console.log("await page.pdf");
    await page.pdf(pdfOptions);

    console.log("await browser.close");
    await browser.close();

})();

Справочную документацию для classList можно найти здесь, например: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList

person sjjhsjjh    schedule 20.11.2019