我正在创建一个简单的QWebEngineView,我试图通过调用js函数来检索一个字符串,但是我没有找到这样做的方法。
这是一个只需调用js函数的工作实例。
from PySide2.QtWebEngineWidgets import QWebEngineView
class View:
def __init__(self):
self.view = QWebEngineView()
self.view.load(QUrl("https://mytestpage.com"))
self.view.show()
def callback(a):
print a
if __name__ == '__main__':
view = View()
view.view.page().runJavaScript("window.getMail()", callback)
getMail
是在浏览器上执行的,但是根据文档,为了得到结果,我需要传入一个回调函数作为第二个参数,但是这样做会产生一个。
TypeError: `runJavaScript() takes exactly one argument (2 given) #
一个可能的解决方案是注入一个QObject,允许使用Qt WebChannel与DOM通信。
import os
import sys
from PySide2 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
from jinja2 import Template
class Element(QtCore.QObject):
loaded = QtCore.Signal()
def __init__(self, name, parent=None):
super(Element, self).__init__(parent)
self._name = name
self._is_loaded = False
@property
def name(self):
return self._name
@property
def is_loaded(self):
return self._is_loaded
@QtCore.Slot()
def set_loaded(self):
self._is_loaded = True
self.loaded.emit()
def render_script(self, script, **kwargs):
kwargs["name"] = self.name
return Template(script).render(**kwargs)
class TestObject(Element):
@QtCore.Slot(str)
def test(self, res):
print(res)
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self, *args, **kwargs):
super(WebEnginePage, self).__init__(*args, **kwargs)
self.loadFinished.connect(self.onLoadFinished)
self._objects = []
def add_object(self, obj):
self._objects.append(obj)
@QtCore.Slot(bool)
def onLoadFinished(self, ok):
if ok:
self.load_qwebchannel()
self.load_objects()
def load_qwebchannel(self):
file = QtCore.QFile(":/qtwebchannel/qwebchannel.js")
if file.open(QtCore.QIODevice.ReadOnly):
content = file.readAll()
file.close()
self.runJavaScript(content.data().decode())
if self.webChannel() is None:
channel = QtWebChannel.QWebChannel(self)
self.setWebChannel(channel)
def load_objects(self):
if self.webChannel() is not None:
objects = {obj.name: obj for obj in self._objects}
self.webChannel().registerObjects(objects)
_script = r"""
{% for obj in objects %}
var {{obj}} = null;
{% endfor %}
new QWebChannel(qt.webChannelTransport, function (channel) {
{% for obj in objects %}
{{obj}} = channel.objects.{{obj}};
{{obj}}.set_loaded()
{% endfor %}
});
"""
self.runJavaScript(Template(_script).render(objects=objects.keys()))
class WebPage(QtWebEngineWidgets.QWebEngineView):
def __init__(self, parent=None):
super().__init__(parent)
page = WebEnginePage(self)
self.setPage(page)
self.test_object = TestObject("test_object", self)
self.test_object.loaded.connect(self.test_object_loaded)
page.add_object(self.test_object)
self.load(QtCore.QUrl("https://mytestpage.com"))
@QtCore.Slot()
def test_object_loaded(self):
script = self.test_object.render_script(
r"""
{{name}}.test(window.getMail());
"""
)
self.page().runJavaScript(script)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
web = WebPage()
web.show()
sys.exit(app.exec_())