
Минимальный веб-браузер можно реализовать на Python с использованием библиотеки PyQt5 и её компонента QtWebEngineWidgets, который основан на движке Chromium. Такой подход позволяет создать окно с возможностью отображения HTML-страниц, навигацией по URL и базовыми элементами управления.
Для запуска потребуется Python версии не ниже 3.7 и установка следующих пакетов через pip: PyQt5 и PyQtWebEngine. Установка выполняется командой pip install PyQt5 PyQtWebEngine. Важно использовать совместимые версии, поскольку несовпадения могут привести к сбоям при инициализации движка рендеринга.
Браузер строится на основе класса QMainWindow. В центральную область окна добавляется виджет QWebEngineView, отвечающий за отображение веб-страниц. Для базовой функциональности необходимо реализовать строку ввода URL, кнопки «вперёд», «назад», «обновить» и «домой». Обработка сигналов от этих элементов подключается напрямую к методам объекта QWebEngineView.
Реализация навигации выполняется с помощью методов load(QUrl), back(), forward() и reload(). Для преобразования строки URL в объект QUrl следует использовать QUrl.fromUserInput(), чтобы обеспечить корректную интерпретацию введённых пользователем адресов. Дополнительно рекомендуется настроить окно так, чтобы оно масштабировалось под разные разрешения экранов, с применением QVBoxLayout или QGridLayout при компоновке элементов.
Такой проект – удобная основа для расширения: добавления закладок, истории посещений, работы с вкладками или ограничения доступа к определённым сайтам. Браузер можно собрать в отдельное приложение с помощью PyInstaller (pip install pyinstaller), указав главный исполняемый файл при сборке.
Выбор библиотеки для отображения веб-страниц: сравнение PyQt и tkinter

PyQt предоставляет компонент QWebEngineView, основанный на движке Chromium. Он поддерживает HTML5, CSS3, JavaScript, работу с DOM, локальное хранилище и заголовки HTTP. Возможна отладка через встроенные инструменты разработчика. Интерфейс на PyQt интегрируется с системой, поддерживает темы, и масштабируется на высоких разрешениях. Недостаток – размер итогового приложения и необходимость установки дополнительных пакетов (например, PyQtWebEngine).
tkinter не имеет встроенного компонента для рендеринга веб-страниц. Единственный рабочий вариант – встраивание Internet Explorer через tkhtml3 или cefpython, что требует сторонних зависимостей и нестабильно работает на современных системах. JavaScript не поддерживается. Отсутствует контроль над безопасностью содержимого и невозможна полноценная интеграция с DOM. tkinter подходит для отображения простых HTML-фрагментов без стилей и скриптов.
Для создания браузера, способного отображать современные сайты, PyQt – единственный разумный выбор. tkinter может использоваться лишь для создания оболочки или панели инструментов, но не как средство отображения контента.
Установка PyQt5 и настройка базового окна приложения
Для создания простого браузера на Python с графическим интерфейсом нужно установить библиотеку PyQt5, которая предоставляет компоненты для работы с GUI. Для этого выполните следующие шаги:
- Откройте командную строку или терминал.
- Введите команду для установки PyQt5 с помощью pip:
pip install PyQt5
После успешной установки можно приступать к созданию базового окна приложения. Для этого создадим файл, например, browser.py, в котором будет находиться основной код для настройки интерфейса.
Основные шаги для настройки базового окна:
- Импортируем необходимые модули:
from PyQt5.QtWidgets import QApplication, QWidget
- Создаём класс для основного окна, наследуя его от
QWidget.
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Простой браузер')
self.setGeometry(100, 100, 800, 600)
В этом коде задаются следующие параметры:
setWindowTitle()– задаёт название окна.setGeometry()– устанавливает начальное положение и размеры окна (x, y, ширина, высота).
- Инициализируем приложение и запускаем главный цикл:
if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() app.exec_()
Этот код создает приложение, отображает окно и запускает главный цикл, который отвечает за обработку событий в окне.
После выполнения этих шагов, вы получите простое окно с заголовком «Простой браузер».
Добавление адресной строки и кнопки перехода по URL

Для реализации адресной строки и кнопки перехода по URL в браузере на Python используем библиотеку Tkinter для создания графического интерфейса и WebEngine (например, PyQtWebEngine) для рендеринга веб-страниц.
Первым шагом добавим текстовое поле для ввода URL, в котором пользователь будет вводить адрес. Для этого используем виджет Entry:
«`python
from tkinter import *
root = Tk()
entry = Entry(root, width=50)
entry.pack(pady=10)
Вторым элементом будет кнопка для перехода по введенному URL. Создадим её с помощью виджета Button:
pythonCopyEditdef navigate():
url = entry.get()
# Код для загрузки URL в веб-просмотре
button = Button(root, text=»Перейти», command=navigate)
button.pack(pady=5)
Теперь добавим функцию для загрузки веб-страницы по указанному URL. Для этого можно использовать библиотеку PyQtWebEngine, которая позволяет интегрировать WebEngine в приложение на Tkinter:
pythonCopyEditfrom PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
app = QApplication([])
webview = QWebEngineView()
webview.setUrl(QUrl(entry.get())) # Загрузка URL из адресной строки
webview.show()
app.exec_()
Такой подход позволяет загружать страницу в встроенном веб-просмотре после нажатия кнопки. Обратите внимание на обработку ввода URL и переход между страницами в браузере. Вы можете расширить функциональность, добавив проверку правильности URL или обработку ошибок.
Для улучшения пользовательского опыта можно добавить автофокус на адресную строку при запуске и очистку поля ввода после перехода. Это повысит удобство использования браузера.
Загрузка веб-страниц с помощью QWebEngineView

QWebEngineView входит в модуль PyQt5.QtWebEngineWidgets и предоставляет встроенный движок на базе Chromium. Для использования необходимо установить пакет PyQtWebEngine. Установка: pip install PyQtWebEngine.
Подключение компонента:
from PyQt5.QtWebEngineWidgets import QWebEngineView
Создание экземпляра и загрузка страницы:
browser = QWebEngineView()
browser.load(QUrl("https://example.com"))
Метод load() принимает объект QUrl, а не строку. Для перехода по адресу из строки – использовать QUrl.fromUserInput("адрес").
Пример загрузки с проверкой готовности:
from PyQt5.QtCore import QUrl
def on_load_finished(ok):
if ok:
print("Загрузка завершена")
else:
print("Ошибка при загрузке")
browser = QWebEngineView()
browser.loadFinished.connect(on_load_finished)
browser.load(QUrl("https://example.com"))
Если нужно загрузить локальный HTML-файл:
browser.load(QUrl.fromLocalFile("/путь/к/файлу.html"))
Для динамической загрузки HTML-кода без перехода по адресу используется метод setHtml():
html_code = "<h1>Пример</h1><p>Локальный HTML</p>"
browser.setHtml(html_code)
Для загрузки HTML с определённым базовым URL, необходимым для корректной работы относительных путей:
browser.setHtml(html_code, baseUrl=QUrl("https://example.com"))
Метод load() загружает страницу асинхронно. Обновления интерфейса и дальнейшие действия нужно выполнять через сигнал loadFinished.
При разработке простого браузера на Python с использованием PyQt5 или PySide2 важно обрабатывать сетевые ошибки, чтобы приложение не завершалось неожиданно и информировало пользователя о причине сбоя.
Для отслеживания ошибок при загрузке страниц необходимо подключиться к сигналу loadFinished(bool) у объекта QWebEngineView. Если аргумент False, значит произошла ошибка. Вместе с этим полезно использовать сигнал QWebEnginePage::loadError для получения кода ошибки и URL.
Пример подключения обработки ошибки:
self.browser.loadFinished.connect(self.handle_load_finished)
В методе handle_load_finished следует проверять статус загрузки и, при ошибке, отображать сообщение через QMessageBox или собственный виджет:
def handle_load_finished(self, success):
if not success:
QMessageBox.warning(self, "Ошибка загрузки", "Не удалось загрузить страницу. Проверьте адрес или подключение к сети.")
Для детального анализа можно использовать QWebEnginePage::setErrorPage или переопределить метод acceptNavigationRequest, чтобы обрабатывать недоступные ресурсы вручную.
Также полезно логировать ошибки в файл с указанием времени, URL и кода ошибки для последующего анализа. Это позволяет выявить проблемные сайты или нестабильное соединение:
with open("error_log.txt", "a") as f:
f.write(f"{datetime.now()} – Ошибка при загрузке: {url}\n")
Нельзя допускать, чтобы при ошибке пользователь оставался без обратной связи. Минимум – всплывающее окно с пояснением. Оптимально – встроенный в интерфейс блок с сообщением и возможностью повторной загрузки.
Реализация кнопок «Назад», «Вперёд» и «Обновить»
Для управления историей навигации потребуется стек. Один стек сохраняет адреса уже посещённых страниц, второй – страницы, к которым можно вернуться вперёд. При переходе по новой ссылке текущий адрес помещается в стек «назад», стек «вперёд» очищается.
Кнопка «Назад» должна извлекать последний адрес из стека «назад», помещать текущий адрес в стек «вперёд» и загружать извлечённый. Если стек пуст, кнопка неактивна. Аналогично работает кнопка «Вперёд», но меняются местами стеки.
Кнопка «Обновить» просто перезагружает текущий URL, без изменения стеков. В случае ошибок подключения рекомендуется предусмотреть повтор запроса с таймаутом.
Пример на PyQt5: у кнопок вызываются методы, манипулирующие QWebEngineView и списками истории. Для «назад» – view.back(), для «вперёд» – view.forward(), для обновления – view.reload(). Но для полного контроля лучше использовать свои списки истории URL-ов, чтобы синхронизировать их с интерфейсом.
Перед переходом всегда сохраняйте текущий URL. Не добавляйте в историю повторяющиеся адреса – это усложняет навигацию. Интерфейс должен реагировать на доступность перехода: кнопки блокируются, если история пуста.
Ограничение доступа: фильтрация URL по списку разрешённых сайтов
Для ограничения доступа в браузере можно реализовать фильтрацию URL по белому списку. Это предотвратит загрузку любых сайтов, не входящих в заранее заданный перечень.
Рекомендуемый способ – использовать список доменов и проверять каждый запрашиваемый URL перед его отображением. Пример базовой реализации на Python с использованием PyQt5:
allowed_hosts = ["example.com", "docs.python.org"]
def is_url_allowed(url):
from urllib.parse import urlparse
host = urlparse(url).netloc
return any(host.endswith(allowed) for allowed in allowed_hosts)
В обработчике перехода по ссылке необходимо вызывать is_url_allowed. Если возвращается False, переход блокируется:
class Browser(QWebEngineView):
def load_url(self, url):
if is_url_allowed(url):
self.setUrl(QUrl(url))
else:
self.setHtml("<h1>Доступ запрещён</h1>")
Рекомендации по составлению белого списка:
- Указывать домены без протокола, например
example.org - Избегать подстановочных символов – сравнение должно быть строгое или на основе
endswith - Проверку выполнять до загрузки страницы, иначе возможен обход
Дополнительно можно отфильтровывать перенаправления, если они ведут на внешние ресурсы. Это потребует анализа заголовков ответа или перехвата событий urlChanged.
Фильтрация на основе списка разрешённых сайтов особенно полезна при создании браузеров для ограниченного доступа – терминалов, учебных классов, детского использования.
Сбор и отображение заголовка и статуса загруженной страницы

Статус ответа доступен через атрибут response.status_code. Для корректной обработки достаточно сравнить значение с диапазоном 200–299. При любом другом статусе рекомендуется отобразить сообщение о проблеме загрузки и сам код.
Пример кода:
import requests
from bs4 import BeautifulSoup
def fetch_page_info(url):
try:
response = requests.get(url, timeout=5)
status = response.status_code
if 200 <= status < 300:
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.title.string if soup.title else 'Заголовок не найден'
else:
title = 'Ошибка загрузки'
return title, status
except requests.RequestException:
return 'Сбой подключения', None
