QWebEngineView не хочет добавлять кастомную схему

FimusPhimosis

Новичок
Пользователь
Фев 25, 2024
11
1
3
ОС: Windows 10
Версия Python 3 (более точной версии не знаю)
Используемые библиотеки: PyQt5

Здравствуйте, я написал свой браузер (с его помощью можно заходить на любые браузеры, которые поддерживают только один браузер). Я решил сделать фишу, чтобы когда пользователь заходил в браузер впервые, то в строку автоматически вбивалась ссылка bb://welcome, но что-то пошло не так и библиотека не хочет поддерживать схему bb://, и ведёт меня на сайт example.com. Я перепробовал все методы которые я знаю, не помогло. Может, кто нибудь здесь ответит на этот вопрос?

Скрипт \/
Python:
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QAction, QLineEdit, QComboBox, QFileDialog, \
    QActionGroup
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtCore import QUrl, QEvent


class CustomWebEnginePage(QWebEnginePage):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.browser = parent

    def acceptNavigationRequest(self, url, type, is_main_frame):
        url_str = url.toString()
        if url_str.startswith("bb://welcome"):
            self.browser.show_tutorial()
            return False
        return super().acceptNavigationRequest(url, type, is_main_frame)


class BilutaBrowse(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("BilutaBrowse")
        self.setGeometry(200, 100, 1200, 800)

        self.theme = 'light'
        self.set_theme(self.theme)

        self.cookies_folder = "cookies"
        os.makedirs(self.cookies_folder, exist_ok=True)

        self.history_file = "history.txt"
        self.downloads_file = "downloads.txt"

        self.browser = QWebEngineView()
        self.setCentralWidget(self.browser)

        self.page = CustomWebEnginePage(self)
        self.browser.setPage(self.page)

        self.check_first_run()

        self.toolbar = QToolBar()
        self.addToolBar(self.toolbar)

        self.url_bar = QLineEdit()
        self.url_bar.returnPressed.connect(self.navigate_to_url)
        self.toolbar.addWidget(self.url_bar)

        back_button = QAction("Back", self)
        back_button.triggered.connect(self.browser.back)
        self.toolbar.addAction(back_button)

        forward_button = QAction("Forward", self)
        forward_button.triggered.connect(self.browser.forward)
        self.toolbar.addAction(forward_button)

        reload_button = QAction("Reload", self)
        reload_button.triggered.connect(self.browser.reload)
        self.toolbar.addAction(reload_button)

        self.user_agent_combo = QComboBox()
        self.user_agent_combo.addItems([
            "Default",
            "Chrome (Windows)",
            "Chrome (Mac)",
            "Firefox (Windows)",
            "Firefox (Mac)",
            "Safari (Mac)",
            "Edge (Windows)",
            "Opera (Windows)"
        ])
        self.user_agent_combo.currentIndexChanged.connect(self.change_user_agent)
        self.toolbar.addWidget(self.user_agent_combo)

        self.cookie_store = self.browser.page().profile().cookieStore()
        self.load_cookies()

        self.browser.urlChanged.connect(self.update_url)

        self.browser.loadFinished.connect(self.save_history)

        self.browser.page().profile().downloadRequested.connect(self.handle_download)

        theme_menu = QToolBar("Themes", self)
        self.addToolBar(theme_menu)

        theme_group = QActionGroup(self)

        light_theme_action = QAction("Light Theme", self, checkable=True)
        dark_theme_action = QAction("Dark Theme", self, checkable=True)

        theme_group.addAction(light_theme_action)
        theme_group.addAction(dark_theme_action)

        light_theme_action.triggered.connect(lambda: self.change_theme('light'))
        dark_theme_action.triggered.connect(lambda: self.change_theme('dark'))

        theme_menu.addAction(light_theme_action)
        theme_menu.addAction(dark_theme_action)

        if self.theme == 'dark':
            dark_theme_action.setChecked(True)
        else:
            light_theme_action.setChecked(True)

    def navigate_to_url(self):
        url = self.url_bar.text()
        if url.startswith("bb://"):
            self.browser.setUrl(QUrl(url))
        elif not url.startswith("http"):
            url = "http://" + url
        self.browser.setUrl(QUrl(url))

    def update_url(self, q):
        self.url_bar.setText(q.toString())

    def change_user_agent(self):
        user_agents = {
            "Default": None,
            "Chrome (Windows)": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Chrome (Mac)": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Firefox (Windows)": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
            "Firefox (Mac)": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0",
            "Safari (Mac)": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15",
            "Edge (Windows)": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.48",
            "Opera (Windows)": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 OPR/77.0.4054.64"
        }

        selected_agent = self.user_agent_combo.currentText()
        user_agent = user_agents.get(selected_agent)

        if user_agent:
            self.browser.page().profile().setHttpUserAgent(user_agent)
        else:
            self.browser.page().profile().setHttpUserAgent("")

        self.browser.reload()

    def load_cookies(self):
        for cookie_file in os.listdir(self.cookies_folder):
            domain = cookie_file
            file_path = os.path.join(self.cookies_folder, domain)
            try:
                with open(file_path, "r") as f:
                    for line in f:
                        name, value = line.strip().split("\t")
                        self.cookie_store.setCookie(name.encode(), value.encode(), QUrl("https://" + domain))
            except Exception as e:
                print(f"Ошибка загрузки куки из файла {file_path}: {e}")

    def save_cookies(self):

        def save_cookie(cookie):
            domain = cookie.domain().lstrip(".")
            file_path = os.path.join(self.cookies_folder, domain)

            with open(file_path, "a") as f:
                cookie_str = f"{cookie.name().data().decode()}\t{cookie.value().data().decode()}\n"
                f.write(cookie_str)

        for cookie_file in os.listdir(self.cookies_folder):
            os.remove(os.path.join(self.cookies_folder, cookie_file))

        self.cookie_store.allCookies(save_cookie)

    def save_history(self):
        current_url = self.browser.url().toString()
        with open(self.history_file, "a") as f:
            f.write(current_url + "\n")

    def handle_download(self, download):
        dialog = QFileDialog()
        save_path, _ = dialog.getSaveFileName(self, "Сохранить файл", download.suggestedFileName())

        if save_path:
            download.setPath(save_path)
            download.accept()

            with open(self.downloads_file, "a") as f:
                f.write(f"Имя файла: {download.suggestedFileName()}\n")
                f.write(f"Путь: {save_path}\n")

    def check_first_run(self):
        if not os.path.exists(self.history_file):
            self.show_tutorial()
            self.url_bar.setText("bb://welcome")
        else:
            self.browser.setUrl(QUrl("http://example.com"))

    def show_tutorial(self):
        tutorial_html = """
        <html>
        <head>
            <style>
                body {{
                    font-family: Arial, sans-serif;
                    background-color: #{};
                    color: #{};
                    padding: 20px;
                }}
                h1 {{
                    font-size: 24px;
                }}
                p {{
                    font-size: 18px;
                }}
                input {{
                    padding: 10px;
                    font-size: 16px;
                    width: 80%;
                }}
                button {{
                    padding: 10px;
                    font-size: 16px;
                }}
            </style>
        </head>
        <body>
            <h1>Добро пожаловать в BilutaBrowse!</h1>
            <p>Это ваш новый браузер с поддержкой куков, истории и загрузок. Наслаждайтесь!</p>
            <p>Вы можете выбрать тёмную или светлую тему в меню.</p>
            <form onsubmit="event.preventDefault(); window.location.href='http://www.google.com/search?q=' + document.getElementById('search').value;">
                <input type="text" id="search" placeholder="Поиск в интернете...">
                <button type="submit">Найти</button>
            </form>
        </body>
        </html>
        """.format("222222" if self.theme == 'dark' else "FFFFFF", "FFFFFF" if self.theme == 'dark' else "000000")

        self.browser.setHtml(tutorial_html)

    def change_theme(self, theme):
        self.theme = theme
        self.set_theme(self.theme)
        self.browser.reload()

    def set_theme(self, theme):
        if theme == 'dark':
            self.setStyleSheet("background-color: #222222; color: #FFFFFF;")
        else:
            self.setStyleSheet("background-color: #FFFFFF; color: #000000;")

    def closeEvent(self, event):
        self.save_cookies()
        event.accept()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = BilutaBrowse()
    window.show()
    sys.exit(app.exec_())
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 646
472
83
потому что в вашей функции def check_first_run(self): ошибка AttributeError: 'BilutaBrowse' object has no attribute 'url_bar', и если закоментить строку self.url_bar.setText("bb://welcome"), он создаст файл history.txt, который вы проверяете при первом запуске, и получается что уже не первый запуск...

а ошибка возникает, потому что вы вызываете функцию check_first_run раньше определения url_bar, опустите в конструкторе ее вызов ниже определения url_bar и все заработает

а в строку не вставляется bb://welcome, потому что у вас какой то конфликт в html коде в функции show_tutorial, если закоментить ее вызов в функции check_first_run, то в строку все вставляется

так же у вас ошибка при закрытии программы, что то не чистите...

дальше разбираться не стал...
 

Форум IT Специалистов