Question

I've been doing testing work in Python using QtWebkit/Spynner. As QtWebKit has Javascript support just like Chrome's Webkit, is it possible to inject a userscript or a piece of javascript at the beginning of a page just like you would a regular user script in Chrome?

Hopefully a simple question for those experience! Thanks in advance!

Was it helpful?

Solution

You can use the following approach:

  1. Register a handler for QWebPage.frameCreated
  2. Inside that event handler, register a new event handler for QWebFrame.javaScriptWindowObjectCleared
  3. In that second event handler, use QWebFrame.evaluateJavaScript (or Spynner's runjs method) to run your Javascript.

This is the approach taken by capybara-webkit to execute its utility scripts. Unfortunately I can't give you example Python code because I'm not familiar with the Qt Python bindings.

OTHER TIPS

From the previous answer (Niklas B.): the capybara-webkit uses a not so useful double subscription of signal-slot (frameCreated-javaScriptWindowObjectCleared), and uses a sender() call in the injectJavascriptHelpers() function that is not a good practice for a decoupled code.

Actually you only need to connect the "javaScriptWindowObjectCleared" signal from the mainFrame() to your slot.

Supposing you are using the old Widget coding style for PyQt (no qml then):

class InstrumentedPage(PyQt5.QtWebKitWidgets.QWebPage):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.loadFinished.connect(self.finished)
        self.mainFrame().javaScriptWindowObjectCleared.connect(self.initYourJavascriptAtTheBeginningHere)

    def javaScriptConsoleMessage(self, message, lineNumber, sourceID):
        message = "%s (%s:%d)" % (message, sourceID, lineNumber)
        self.__logger.info("JS :: %s" % message )

    def initYourJavascriptAtTheBeginningHere(self):
        js = "console.log(\"INITED\");"
        self.mainFrame().evaluateJavaScript(js)

    def injectYourJavascriptHere(self, js):
        return self.mainFrame().evaluateJavaScript(js)

    def finished(self, status):
        self.__logger.info("InstrumentedPage.finished() :: init status => %s" % status)

class MainWindow(PyQt5.QtWidgets.QWidget):

    def __init__(self, config, config_file_name, parent=None):
        super().__init__(parent)

        self.ui = Ui_MainWindow.Ui_MainWindow()
        self.ui.setupUi( self )

        self.web_page = InstrumentedPage()
        self.ui.webView.setPage(self.web_page)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top