【问题标题】:Qt WebView - intercept loading of JS/CSS Libraries to load local onesQt WebView - 拦截加载 JS/CSS 库以加载本地库
【发布时间】:2018-08-27 23:14:49
【问题描述】:

我一直在通过文档寻找一种方法来实现这一点,但还没有成功。基本思想是,我有一段通过 Qt 的 webview 加载的 html。可以将相同的内容导出到单个 html 文件中。

此文件使用 Bootstrap 和 jQuery 等库。目前我通过 CDN 加载它们,这在在线时可以正常工作。但是,我的应用程序也需要离线运行。所以我正在寻找一种方法来拦截 Qt 中库的加载并提供本地保存的文件。我试过安装一个 https QWebEngineUrlSchemeHandler,但这似乎永远不会触发它的 requestStarted 方法。

(PyQT example follows)
QWebEngineProfile.defaultProfile().installUrlSchemeHandler(b'https', self)

如果我为方案使用不同的文本并将其嵌入到页面中它可以工作,所以我的假设是它不起作用,因为 Qt 已经注册了一个默认处理程序。但是这种不同的方案在文件导出中会失败。

不管怎样,回到核心问题;有没有办法拦截库的加载,或者只在 Qt 中专门更改 url 方案?

使用 QWebEngineUrlRequestInterceptor 更进一步,现在将 https 请求重定向到我自己的 uri,它有一个 uri 处理程序。但是,请求永远不会通过它,因为: 重定向位置 'conapp://webresource/bootstrap.min.css' 有一个不允许的跨域请求方案。 如何将我自己的 conapp uri 方案列入白名单?

编辑:为了完整起见,当我最初提出这个问题时,事实证明,由于其中的错误,PySide 5.11 不可能完成。我当时报告的错误现在已标记为已修复(我相信是 5.12.1),因此现在应该可以使用 Qt 方法再次完成此操作,但是对于我自己的项目,我现在将坚持使用 jinja,这已成为一种解决方案解决许多其他问题。

【问题讨论】:

标签: qt pyqt pyqt5 url-scheme qwebview


【解决方案1】:

以下示例显示了我是如何做到的。它使用 QWebEngineUrlRequestInterceptor 将内容重定向到本地服务器。

作为一个例子,我截取stackoverflow的stacks.css并做出明显的改变。

import requests
import sys
import threading
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineProfile
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor, QWebEngineUrlRequestInfo
from http.server import HTTPServer, SimpleHTTPRequestHandler
from socketserver import ThreadingMixIn

# Set these to the address you want your local patch server to run
HOST = '127.0.0.1'
PORT = 1235

class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
    def patch_css(self, url):
        print('patching', url)
        r = requests.get(url)
        new_css = r.text + '#mainbar {background-color: cyan;}'  # Example of some css change
        with open('local_stacks.css', 'w') as outfile:
            outfile.write(new_css)
    def interceptRequest(self, info: QWebEngineUrlRequestInfo):
        url = info.requestUrl().url()
        if url == "https://cdn.sstatic.net/Shared/stacks.css?v=596945d5421b":
            self.patch_css(url)
            print('Using local file for', url)
            info.redirect(QtCore.QUrl('http:{}:{}/local_stacks.css'.format(HOST, PORT)))

class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
    """Threaded HTTPServer"""

app = QtWidgets.QApplication(sys.argv)

# Start up thread to server patched content
server = ThreadingHTTPServer((HOST, PORT), SimpleHTTPRequestHandler)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()

# Install an interceptor to redirect to patched content
interceptor = WebEngineUrlRequestInterceptor()
profile = QWebEngineProfile.defaultProfile()
profile.setRequestInterceptor(interceptor)

w = QWebEngineView()
w.load(QtCore.QUrl('https://stackoverflow.com'))
w.show()
app.exec_()

【讨论】:

    【解决方案2】:

    所以,我最终采用的解决方案是,首先,引入 jinja 模板。然后,使用这些模板将根据导出或内部使用设置变量和块,从那里我不再需要拦截器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 2012-11-25
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多