Content scripts

Content scripts представляют собой фрагменты кода JavaScript, которые выполняются в контексте веб-страницы, управляемой Puppeteer. Они позволяют взаимодействовать напрямую с DOM, получать и изменять данные страницы, запускать пользовательские скрипты и интегрироваться с динамическим контентом.


Выполнение кода на странице

Основным методом для внедрения content script в Puppeteer является page.evaluate(). Он принимает функцию, которая выполняется в браузере, а не в Node.js:

const puppeteer = require(&

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://example.com');

    const title = await page.evaluate(() => {
        return document.title;
    });

    console.log('Title страницы:', title);
    await browser.close();
})();

Особенности использования page.evaluate():

  • Функция выполняется в браузере, поэтому доступна только DOM API, объекты window и document.
  • Любые переменные Node.js внутри функции недоступны. Данные можно передавать через аргументы:
const selector = 'h1';
const headerText = await page.evaluate((sel) => {
    const element = document.querySelector(sel);
    return element ? element.textContent : null;
}, selector);
  • Возвращаемое значение автоматически сериализуется из браузера в Node.js. Сложные объекты (например, функции или DOM-узлы) не могут быть переданы напрямую.

Работа с асинхронными операциями

Content scripts поддерживают асинхронные функции и await для работы с промисами:

const data = await page.evaluate(async () => {
    const response = await fetch('https://api.example.com/data');
    const json = await response.json();
    return json;
});

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


Множественные скрипты и порядок выполнения

Puppeteer поддерживает выполнение нескольких content scripts на одной странице. Важным аспектом является правильный порядок выполнения, особенно при модификации DOM:

await page.evaluate(() => {
    document.body.style.backgroundColor = 'lightblue';
});

await page.evaluate(() => {
    const header = document.createElement('h1');
    header.textContent = 'Заголовок добавлен скриптом';
    document.body.appendChild(header);
});
  • Первым изменяется фон страницы.
  • Затем добавляется новый элемент в DOM.
  • Порядок await обеспечивает последовательное выполнение, предотвращая коллизии.

Инъекция внешних скриптов

Для больших content scripts иногда удобнее загружать внешние JavaScript-файлы, чем писать весь код внутри page.evaluate(). Это делается с помощью page.addScriptTag():

await page.addScriptTag({ path: './contentScript.js' });
await page.evaluate(() => {
    initContentScript();
});
  • Скрипт подключается на страницу, как если бы он был включён через <script> в HTML.
  • Можно использовать функции, объявленные в файле, после его подключения.
  • Поддерживаются пути файлов (path) и URL (url) для удалённых ресурсов.

Взаимодействие с DOM элементов

Content scripts идеально подходят для манипуляций с элементами страницы: выборка, изменение атрибутов, клик, ввод текста. Для этого удобно комбинировать page.evaluate() с методами Puppeteer для элементных хэндлов:

const buttonSelector = '#submit';

await page.evaluate((sel) => {
    const button = document.querySelector(sel);
    if (button) button.click();
}, buttonSelector);

const inputValue = await page.$eval('#username', el => el.value);

Различие между методами:

  • page.eval(selector, fn) < /code > —выполняетфункциютолькодляодногоэлемента. < /li >  < li >  < code > page.$eval(selector, fn) — выполняет функцию для массива элементов.

Передача данных из Node.js в content script

Для динамических операций важно передавать данные из Node.js в браузер:

const userData = { name: 'Alex', age: 30 };

await page.evaluate((data) => {
    const div = document.createElement('div');
    div.textContent = `Имя: ${data.name}, Возраст: ${data.age}`;
    document.body.appendChild(div);
}, userData);
  • Любые объекты и массивы сериализуются через JSON.
  • Функции, RegExp и сложные объекты не могут быть переданы напрямую.

Логирование и отладка

Content scripts выполняются в контексте страницы, поэтому обычный console.log выводит сообщения в консоль браузера, а не Node.js. Чтобы получать вывод, используются события страницы:

page.on('console', msg => console.log('Browser log:', msg.text()));

await page.evaluate(() => {
    console.log('Сообщение из контент скрипта');
});

Это позволяет отслеживать поведение скриптов, ошибки и внутренние данные страницы.


Ограничения и рекомендации

  1. Content scripts не имеют доступа к Node.js API, только к веб-окружению.
  2. Работа с асинхронным DOM (динамически подгружаемые элементы) требует ожидания с помощью waitForSelector или циклов проверки.
  3. Для сложных скриптов лучше использовать отдельные файлы и addScriptTag, чтобы сохранить читаемость и модульность.
  4. Любые изменения DOM должны учитывать возможные конфликты с существующими скриптами страницы.

Пример комплексного content script

await page.goto('https://example.com');

// Ждем загрузки основного контента
await page.waitForSelector('h1');

await page.evaluate(() => {
    // Меняем цвет всех заголовков
    document.querySelectorAll('h1, h2, h3').forEach(el => {
        el.style.color = 'darkred';
    });

    // Добавляем уведомление
    const notice = document.createElement('p');
    notice.textContent = 'Контент модифицирован скриптом';
    document.body.prepend(notice);
});

// Получаем итоговое содержимое страницы
const html = await page.content();
console.log(html.slice(0, 300));

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


Content scripts в Puppeteer обеспечивают мощный и гибкий механизм взаимодействия с веб-страницами. Правильное использование page.evaluate, addScriptTag, а также методов работы с DOM позволяет создавать сложные автоматизации и тесты, интегрированные в динамические интерфейсы.