2025, Oct 05 09:16

Тихий headless запуск Chrome через Selenium: убираем логи

Разберём, как запустить Chrome через Selenium в headless и приглушить лишние логи: os.devnull для ChromeDriver, уровни logging в Python и флаг --log-level=3.

Запуск Chrome через Selenium в безголовом режиме и одновременное подавление шумных стартовых логов на первый взгляд кажется простым переключателем — пока не выясняется, что это не так. Типичная ловушка: удаётся добиться лишь одной цели — либо headless включён, но логи сыплются повсюду, либо логи подавлены, зато окно браузера всплывает. Корневая причина в том, что сообщения приходят из разных слоёв, и каждый из них нужно глушить отдельно.

Как воспроизвести проблему

Ниже фрагмент, который при необходимости включает headless и пытается приглушить логи через опции Chrome, однако при некоторых запусках вывод всё равно появится:

import sys
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
chrome_prefs = webdriver.ChromeOptions()
chrome_prefs.add_experimental_option("excludeSwitches", ["enable-logging"])  
if not ("-dhl" in sys.argv or "--disable-headless" in sys.argv):
    chrome_prefs.add_argument("--headless=new")
browser_client = webdriver.Chrome(
    service=Service(ChromeDriverManager().install()),
    options=chrome_prefs
)
browser_client.get("https://google.com")

Что происходит на самом деле

Вывод, который вы видите, — не единый поток. Есть логи процесса ChromeDriver, журналирование Python‑библиотек urllib3, selenium, WDM и webdriver-manager, а также собственные логи Chrome. Включение безголового режима не заставляет драйвер замолчать, а отключение Python‑логгеров не мешает самому процессу драйвера писать в свой вывод. Поэтому и создаётся впечатление, что можно «заставить работать только что‑то одно».

Решение: глушим каждый источник сообщений по отдельности

Для начала направьте вывод ChromeDriver в нулевое устройство ОС, чтобы сам драйвер перестал писать в консоль. Затем уменьшите многословность логгеров на стороне Python и понизьте уровень журналирования самого Chrome. В сумме эти шаги позволяют одновременно запускать headless и держать консоль чистой.

import os
import sys
import logging
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
chr_flags = webdriver.ChromeOptions()
chr_flags.add_experimental_option("excludeSwitches", ["enable-logging"])  
if not ("-dhl" in sys.argv or "--disable-headless" in sys.argv):
    chr_flags.add_argument("--headless=new")
chr_flags.add_argument("--log-level=3")
svc = Service(
    ChromeDriverManager().install(),
    log_output=os.devnull
)
logging.getLogger("selenium").setLevel(logging.CRITICAL)
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
logging.getLogger("WDM").setLevel(logging.CRITICAL)
logging.getLogger("webdriver_manager").setLevel(logging.CRITICAL)
client = webdriver.Chrome(service=svc, options=chr_flags)
client.get("https://google.com")

Если хотите более жёсткий подход на стороне Python, установите уровень корневого логгера так, чтобы всё ниже CRITICAL и FATAL отфильтровывалось:

import logging
logging.getLogger().setLevel(logging.CRITICAL)

Имейте в виду, что некоторые сообщения, например строка «DevTools listening …», сейчас трудно подавить полностью. Это известное ограничение.

Почему это важно

Безголовые запуски — основа CI‑пайплайнов и серверной автоматизации. Чистые логи делают сбои очевидными, ускоряют разбор и не засоряют артефакты. Понимание того, что разные подсистемы выводят сообщения независимо, экономит время, которое иначе уходит на бессмысленное перещёлкивание одних и тех же флагов.

Дополнительные замечания

Если нужно зайти ещё дальше, перенаправление stderr на уровне процесса может приглушить остаточные сообщения, но оно же способно скрыть важные ошибки позже. Используйте с осторожностью:

import os, sys
sys.stderr = open(os.devnull, "w")

Отдельно стоит отметить, что webdriver_manager устарел и не поддерживается. В Selenium есть собственный механизм загрузки и управления драйверами — Selenium Manager. Хотя это напрямую не связано с подавлением логов, это хороший путь для поддержки окружения в будущем.

Итог

Ключ к «тихому» безголовому запуску Chrome — относиться к логированию как к задаче с несколькими источниками. Перенаправьте вывод ChromeDriver в os.devnull, снизьте многословность для urllib3, selenium, WDM и webdriver-manager и убавьте уровень логирования самого Chrome. С этими шагами headless‑исполнение и тихая консоль перестают быть взаимоисключающими.

Статья основана на вопросе с StackOverflow от Ahmad и ответе 0ro2.