Is there any way to get class of the page in Pyqt5 in browser?

夙愿已清 提交于 2020-03-18 10:06:26

问题


I am working with pyqt5. I want the user to click on the browser which should be embeded on my pyqt5 application to get the Class of the element which he/she is clicking on it.

I just found on stack overflow that it's doable by combining javascript code with python. Any idea how to extract the class of the element?


回答1:


The solution is to add an "event listener" that makes possible communication between the DOM objects and (Py)Qt.

The following solution is based on this answer.

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
from jinja2 import Template

class Element(QtCore.QObject):
    def __init__(self, name, parent=None):
        super(Element, self).__init__(parent)
        self._name = name

    @property
    def name(self):
        return self._name

    def script(self):
        return ""

class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
    def __init__(self, parent=None):
        super(WebEnginePage, self).__init__(parent)
        self.loadFinished.connect(self.onLoadFinished)
        self._objects = []
        self._scripts = []

    def add_object(self, obj):
        self._objects.append(obj)

    @QtCore.pyqtSlot(bool)
    def onLoadFinished(self, ok):
        print("Finished loading: ", ok)
        if ok:
            self.load_qwebchannel()
            self.add_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 add_objects(self):
        if self.webChannel() is not None:
            objects = {obj.name: obj for obj in self._objects}
            self.webChannel().registerObjects(objects)
            _script = """
            {% for obj in objects %}
            var {{obj}};
            {% endfor %}
            new QWebChannel(qt.webChannelTransport, function (channel) {
            {% for obj in objects %}
                {{obj}} = channel.objects.{{obj}};
            {% endfor %}
            }); 
            """
            self.runJavaScript(Template(_script).render(objects=objects.keys()))
            for obj in self._objects:
                if isinstance(obj, Element):
                    self.runJavaScript(obj.script())


class Helper(Element):
    classClicked = QtCore.pyqtSignal(str)

    def script(self):
        js = """
        document.addEventListener('click', function(e) {
            e = e || window.event;
            var target = e.target || e.srcElement;
            {{name}}.objectClicked(target.className);
        }, false);"""
        return Template(js).render(name=self.name)

    @QtCore.pyqtSlot(str)
    def objectClicked(self, className):
        if className:
            self.classClicked.emit(className)

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    classname_helper = Helper("classname_helper")
    classname_helper.classClicked.connect(lambda name: print("clicked", name))
    view = QtWebEngineWidgets.QWebEngineView()
    page = WebEnginePage()
    page.add_object(classname_helper)
    view.setPage(page)
    view.load(QtCore.QUrl("https://stackoverflow.com/questions/60524774"))
    view.show()
    sys.exit(app.exec_())


来源:https://stackoverflow.com/questions/60524774/is-there-any-way-to-get-class-of-the-page-in-pyqt5-in-browser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!