Qt WebView - intercept loading of JS/CSS Libraries to load local ones

The following example shows how I've done it. It uses the QWebEngineUrlRequestInterceptor to redirect content to a local server.

As an example, I intercept the stacks.css for stackoverflow and make an obvious change.

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_()