Только программисты и айтишники могли придумать такой термин, как «безголовый» браузер. В английском варианте он же будет звучать как headless browser или как decoupled browser (то есть «отделённый» браузер, своего рода намёк на обезглавливание).
Если детальнее разобраться в значении термина, то становится понятна причина такой игры слов. В этом действительно что-то есть, ведь как бы вы разговаривали с человеком, у которого нет головы? Голова в нашем случае – основной интерфейс, по которому считывается речь, мимика и всё прочее.
Заинтриговали? Тогда давайте погрузимся глубже и разберёмся причём тут безголовые браузеры и парсинг данных.
Что такое безголовый (headless) браузер?
Буквальный перевод слов мы уже привели выше.
Headless-браузер – это термин, пришедший из программирования. Дело в том, что в настоящее время многие крупные движки сайтов (CMS-системы), стали отделять основное ядро от графических интерфейсов. Это касается как интерфейсов управления и настройки, так и интерфейсов, отображаемых конечным пользователям.
Вместо этого работа интерфейсов может переноситься в сферу ответственности других служб. Например, за работу на мобильных будут отвечать оригинальные (нативные) мобильные приложения, а за отрисовку страниц в десктопных браузерах будут отвечать PWA-приложения. При этом одно тело (движок) может «общаться» с разными «головами», то есть с интерфейсами. Нагрузка на ядро получается минимальная. Так каждая из составных частей занимается своей задачей и может быть оперативно масштабирована. Такие типы CMS-систем как раз и называются Headless CMS.
По аналогии происходит и с браузерами.
Для задач программистов не всегда нужны графические интерфейсы. Более того, есть задачи, где графический режим будет только мешать. И парсинг данных – как раз такая задача.
Headless-браузер (безголовый браузер) – это браузер, который не имеет графического интерфейса, вся работа с ним происходит только через специальный программный интерфейс (через API).
Для чего используется headless-браузер?
Для стандартных задач парсинга вполне подходят готовые библиотеки, способные анализировать структуру HTML-документа, находить нужные теги и вытаскивать из них интересующую нас информацию (данные). О таких библиотеках мы рассказывали ранее:
Но основная проблема в том, что многие современные сайты перестали отдавать «чистый» HTML клиентам. Многие операции обсчитываются и доделываются непосредственно на месте – внутри браузера, то есть на устройстве пользователя, благодаря скриптам JavaScript.
Сайты стали работать как полноценные веб-приложения. Любое действие пользователя, в том числе и простое перемещение по странице, может приводить к изменению вёрстки и, соответственно, к изменению контента.
Если говорить о коде, то вместо классической HTML-разметки ваш парсер будет получать ссылки на исполняемые JS-скрипты, которые в свою очередь могут храниться параллельно в разных местах. Получается, что, чтобы привести HTML-код к его конечному виду, нужно скачать все эти скрипты, выполнить их (применить к базовому HTML, отправленному изначально по HTTP-протоколу) и только потом начинать парсить.
Ни одна библиотека для парсинга так делать не умеет. Проще сразу «прогнать» страницу через браузер и получить у него результирующий HTML-код.
Как раз для этих задач и нужны headless-браузеры:
- Парсер передаёт headless-браузеру адрес целевой страницы и порядок действий (если нужна авторизация, фокусировка на элементе, определённое время задержки и т.п.).
- Браузер работает со страницей, как если бы это делал простой пользователь. Соответственно, выполняются и обсчитываются все связанные JS-скрипты.
- На выходе формируется итоговая HTML-страница.
- Этот результирующий код уже можно передать на обработку парсеру.
Далее парсер действует по своему стандартному алгоритму – находит нужные метки или HTML-теги, вытаскивает из них данные, сохраняет в таблице, выгружает в другой софт и пр.
Получается, что headless-браузер нужен только для полной и всесторонней отрисовки страниц, имеющих большой объём JS-скриптов. Такой браузер используется всего лишь на одном из шагов работы парсера.
Всё общение парсера и headless-браузера происходит без графического интерфейса – по API.
Для чего ещё могут применяться headless-браузеры кроме парсинга:
- Тестирование макетов (дизайна, вёрстки, поиск ошибок, проблем, отрисовка дизайна на разных типах экранов и т.п.).
- Тестирование производительности сайтов и отдельных страниц (кода движка).
- Автоматизация других рутинных задач (тут, например, многие могут вспомнить про мультиаккаунты или про накрутки в социальных сетях).
Headless-режим браузера
Обратите внимание, Google Chrome и некоторые другие браузеры предоставляют готовые интерфейсы для подключения в «безголовом» режиме. Так, программистам доступны специальные средства отладки, API, библиотеки и прочее.
Но сам браузер может оповещать сайт о том, что он работает в headless-режиме. Этот факт могут использовать продвинутые антифрод-системы. Любая попытка обращения к страницам с признаком headless-подключения будет приводить к блокировке IP или к другим неприятным последствиям.
В связи с этим, озаботьтесь использованием библиотек и скриптов, очищающих соответствующие признаки из HTTP-запросов и ответов при парсинге.
Про то, как правильно парсить и не нарываться на блокировки.
Популярные headless-браузеры
Сейчас никого не удивишь, сказав, что все браузеры строятся либо на движке Хромиума (Google Chrome, Яндекс.Браузер, Edge, Opera и пр.), либо на движке Gecko/Quantum (Firefox, Waterfox, Pale Moon, Basilisk и пр.).
Но headless-браузер – это не только ядро для исполнения JS-скриптов, это ещё и специальный набор инструментов для разработчиков, а также специальные модули расширения и библиотеки.
Итак, какие варианты окружений headless-браузеров имеются в наличии?
Chrome DevTools Protocol
Начиная с 59 версии браузера (с 2017 года) разработчики браузера предоставили возможность использования специального API-интерфейса – Chrome DevTools protocol. Всё, что вам нужно – установить браузер и начать работать.
Управление безголовым Хромом осуществляется на уровне командной строки (CLI-режим). Обращаться нужно к стандартному исполняемому файлу браузера, но с особым флагом «--headless».
Среди дополнительных флагов есть инструменты для выгрузки PDF-файлов, создания скриншотов страниц, для отладки, а также для печати DOM-структуры.
Уже только в этом режиме много сделать много всего полезного. Например, можно написать скрипт для командной строки, который будет последовательно обходить страницы сайта, выгружать содержимое в HTML-файлы и передавать на анализ парсеру.
Но для более сложных и продвинутых алгоритмов автоматизации лучше использовать специальные библиотеки, о них ниже.
Почитать больше о возможностях командной строки для Chrome можно в официальной документации браузера.
Библиотека chrome-remote-interface
Это низкоуровневая библиотека, поставляемая в виде npm-пакета. Она использует интерфейс отладки оригинального браузера Хром и умеет делать много мелких действий.
Собственно, именно эта библиотека часто используется для абстракции команд других библиотек и утилит высокого уровня, в том числе при написании своих парсеров.
Chrome-remote-interface обеспечивает максимальную близость к аппаратной составляющей. Но у библиотеки есть и свои минусы, например, она не умеет автоматически запускать экземпляр браузера. Для этого нужно использовать дополнительные средства, такие как ChromeLauncher.
Puppeteer + Headless Chrome
Puppeteer (буквально переводится как «Кукловод») – это молодой, но крайне амбициозный проект. Всё дело в том, что библиотека разрабатывается и сопровождается командой Хрома. Представляет собой Node.js-библиотеку, реализующую высокоуровневый API-интерфейс для работы с безголовым Google Chrome.
Может похвастаться простым и понятным синтаксисом, огромным количеством расширений и интеграций, поддержкой развёртывания в Docker-контейнерах, качественной документацией.
К минусам Puppeteer можно отнести отсутствие поддержки аудио/видео, только программный рендеринг, отсутствие функционала для управления закладками и паролями браузера.
Selenium (Headless Chrome + Headless Firefox)
Selenium – это мощное и комплексное решение, которое позволяет использовать полноценный браузер Chrome в составе автоматических скриптов. Обратите внимание, Selenium требует для своей работы специальный драйвер, WebDriver или ChromeDriver. Последние работают не с безголовым браузером, а с полноценным. То есть эти библиотеки нужны для того, чтобы обычный браузер фактически переделать в безголовый (добавить ему headless-режим).
Так как драйверы можно добавить к разным браузерам, не только к Хрому, то Selenium успешно работает с браузером Firefox, Opera, IE и пр.
Поверх Селениума можно использовать решения более высокого уровня, например, такие библиотеки, как WebDriverIO. В итоге на выходе можно получить готовое высокоуровневое API.
Selenium долгое время оставался самым популярным решением для организации headless-браузеров. И это не потому, что он единственный в своём роде, а потому, что разработчики максимально комплексно подошли к вопросу. В наличии имеются готовая реализация сервера, IDE (среда разработки для быстрого написания своих скриптов автоматизации), драйвера практически для любых версий браузеров (от Android-приложений до Internet Explorer и Safari), а также Selenium Grid (среда для массового управления большим количеством безголовых браузеров).
Уже догадываетесь на базе чего делается большинство антидетект-браузеров?
HtmlUnit
HtmlUnit – это одна из немногочисленных попыток написать решение, способное обрабатывать и рендерить JS-скрипты без задействования полноценных браузеров.
HtmlUnit написан на Java и используется в качестве безголового браузера внутри других высокоуровневых решений для тестирования и парсинга: JWebUnit, Canoo WebTest, Serenity BDD, WebDriver, Arquillian Drone и пр.
Что интересно, HtmlUnit умеет имитировать любой браузер и работать через прокси. В наличии даже встроенный парсер и простейшие средства эмуляции поведения пользователей (переход по ссылкам, отправка форм, аутентификация и пр.).
Отдельно об антидетект-браузерах
Мало кто согласен писать свой собственный браузер с нуля. Именно поэтому Майкрософт отказалась от поддержки IE и открыто перешла на движок конкурента (Хром).
Практически все антидетект-браузеры – это набор из разных готовых решений. Чаще всего в основе связка из Chromium, Selenium и некоторых других библиотек. По этой причине у многих из них можно найти готовые API для автоматизации или инструкции по интеграции через WebDriver/ChromeDriver.
По этой причине антидетект-браузеры не стоит рассматривать как самостоятельные headless-браузеры. Это своего рода готовые сборки для определённых задач.
Существуют и менее распространённые решения для поддержки парсинга JavaScript-сайтов, но они либо заброшены, либо не имеют такого уровня поддержки, как решения, обозначенные выше. Речь о таких фреймворках, как Splinter, PhantomJS, Nightmare JS или Playwright.
Парсинг с помощью headless-браузера
Приведём простой пример парсинга на JavaScript, использовать будем Puppeteer (соответственно в связке с Хромом).
//Устанавливаем puppeteer с помощью пакетного менеджера NPM
npm i puppeteer
//Создаём и загружаем новый экземпляр headless-браузера
const browser = await puppeteer.launch({
headless: false,
});
//Запускаем процесс работы с новой страницей
const page = await browser.newPage();
//Переходим на страницу с адресом https://site.com/index.html
await page.goto("https://site.com/index.html" , {
//Ждём, пока страница полностью прогрузится
waitUntil: 'domcontentloaded'
})
//Запустим JavaScript-скрипт в конце целевой страницы
let data = await page.evaluate(() => {
//Найдём на странице все элементы с тегом H1
return Array.from(document.querySelectorAll("article h1")).map((el) => {
return {
//Найдём первый элемент с тегом Title
title: el.querySelector("a").getAttribute("title"),
//Найдём элемент с тегом HREF
link: el.querySelector("a").getAttribute("href"),
};
});
});
//Выведем содержимое тегов в консоль
console.log(data)
//Закроем экземпляр браузера
await browser.close();
Это только один из вариантов того, как будет выглядеть парсинг с применением headless-браузера.
Конкретно в вашем проекте может применяться любой другой язык программирования и разные наборы окружений (headless-браузеров и связанных с ними библиотек). Поэтому будут отличаться: и синтаксис, и собираемые данные, и исходные конфигурации.
Puppeteer работает только с Javascript. Но, например, Selenium может работать практически с любыми языками, версиями браузеров и платформами. Можно даже создать свой собственный web-сервис, отвечающий за парсинг конкретного сайта или сразу разных типов сайтов.
Конкретные команды и документацию по API можно найти в официальной документации и в сообществах выбранных headless-браузеров (профильных библиотек).
Преимущества и недостатки безголовых браузеров
Основные плюсы от использования безголовых браузеров можно обозначить так:
- Только через headless-браузеры открывается возможность работы с современными web-приложениями и JavaScript-сайтами.
- Благодаря API и качественной документации можно автоматизировать буквально любые действия, в том числе эмулировать поведение реального человека. Один только этот факт поможет обойти даже очень сложные системы защиты.
- Благодаря отсутствию графического интерфейса и реального аппаратного рендеринга, ускоряется обработка страниц и процесс получение контента, потребляется меньше ресурсов (если сравнивать с работой полноценного браузера).
- При правильной настройке и использовании прокси, параллельно можно запускать большое число независимых экземпляров браузеров и ускорять парсинг.
- Многие библиотеки для работы с headless-браузерами являются высокоуровневыми, что значительно уменьшает объём работы при написании собственных парсеров. Более того, иногда парсер может быть встроенным решением, нужно просто задействовать его и не придумывать свой «велосипед».
К минусам headless-браузеров можно отнести следующие моменты:
- Нужно понимать, что потребление ресурсов можно считать сниженным только по сравнению с полноценной версией браузера, но если говорить о программной реализации, то каждый headless-браузер потребляет нереально много ресурсов – заметно больше, чем любая другая библиотека для парсинга или фреймворк. Каждая новая страница занимает почти столько же памяти и ресурсов на рендеринг, сколько и полноценный браузер с графическим интерфейсом.
- У каждой библиотеки свои особенности и нюансы – нужно знать API и основные команды.
- Отдельные продвинутые системы защиты сайтов научились обнаруживать headless-браузеры и умеют их блокировать. Соответственно, для полноценного парсинга нужно научиться обходить такую защиту (переделать структуру запросов, увеличить задержки и т.п.).
- Наличие headless-браузера не решает проблему парсинга JavaScript-сайтов до конца. Это лишь решение части проблемы. Браузер ещё нужно подключить, настроить, парсер нужно написать и только потом интегрировать с безголовым браузером.
- Headless-браузеры рендерят страницы только на программном уровне. Из-за этого может возникать ряд особенных проблем.
Выводы и рекомендации
Безголовые браузеры – это эффективное и практически единственное адекватное решение проблемы с парсингом динамических сайтов, задействующих на страницах технологии AJAX и JavaScript.
С недавних пор headless-режим имеется в браузерах Google Chrome, но в остальных случаях для обращения к браузеру понадобится специальный драйвер и библиотека, реализующая API-интерфейс, например, как Selenium.
Поэтому, чтобы написать полноценный парсер, способный учитывать все технические нюансы и настройки, придётся потратить много времени и сил.
В любом случае, если вам нужна высокая скорость скрейпинга, без использования прокси не обойтись. Лучшие мобильные и резидентные прокси можно приобрести у нас.
Froxy – это огромная сеть IP-адресов с динамической ротацией, более 8,5 млн. точек, 200+локаций, точность подбора – до уровня города и провайдера связи. Оплата осуществляется только за пакеты трафика, а не за конкретные прокси. Параллельно можно использовать до 1000 портов.