使用PyQt获取动态内容

时间:2017-01-26 16:06:42

标签: javascript jquery pyqt pyqt4 pyqt5

我需要获取一个动态内容,即由ajax js调用加载。

我真的不知道如何使用PyQt,但我希望我能做到这一点。 HTML类似于:

<a href="#" id="id" onclick="A4J.AJAX.Submit('j_id0:j_id1:j_id110',event,{'similarityGroupingId':'j_id0:j_id1:j_id110:j_id582:0:j_id584'});return false;">NETHERLANDS</a>`

我可以使用这个简单的代码使用PyQt渲染页面:

def render(source_html):

    import sys
    from PyQt5.QtCore import QEventLoop
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWebEngineWidgets import QWebEngineView

    class Render(QWebEngineView):
        def __init__(self, html):
            self.html = None
            self.app = QApplication(sys.argv)
            QWebEngineView.__init__(self)
            self.loadFinished.connect(self._loadFinished)
            self.setHtml(html)

            while self.html is None:
                self.app.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers | QEventLoop.WaitForMoreEvents)
            self.app.quit()

        def _callable(self, data):
            self.html = data

        def _loadFinished(self, result):
            self.page().toHtml(self._callable)

    return Render(source_html).html

import requests
sample_html = requests.get('https://riverbankcomputing.com/software/pyqt/').text
print(render(sample_html))

我如何运行'onclick'并获取内容?

1 个答案:

答案 0 :(得分:3)

这是一个老问题,但是......

从javascript运行PyQt函数:

虽然可能有很多方法可以做到这一点,但我已经使用QWebChannel解决了这个问题,然后从你的html调用了js函数,然后使用网络通道与Qt进行通信。

您需要qwebchannel.js。我从我本地机器上的Qt5示例目录中获取了我的。许多地方的网络上都存在相同的文件。我会留给你找到它。

此处描述了大部分此方法:http://doc.qt.io/qt-5/qtwebchannel-javascript.html

__init__中,创建一个网络频道:

self.webchannel = QtWebChannel.QWebChannel(self)

然后设置webengineview的主页面以使用该频道,并注册要在PyQt和js之间共享的对象:

self.page().setWebChannel(self.webchannel)
self.webchannel.registerObject('MyChannel', self)

在.js(或.html的javascript部分)中,设置网络频道:

var MyChannel = null;
new QWebChannel(qt.webChannelTransport, function(channel) {
                MyChannel = channel.objects.MyChannel;
});

(这是qwebchannel.js发挥作用的地方。你的js或html文件必须能够包含它。对我来说,我在做任何其他js之前加载了<script src="scripts/qwebchannel.js"></script>

现在你已经设置了通过频道从js到PyQt的调用,但是你可以调用什么?任何装饰为PyQt插槽的东西。因此,例如,如果在javascript中,您想在Render中调用一个以字符串作为参数的“foo”函数,那么您将创建它(作为Render的成员),如下所示:

@QtCore.pyqtSlot(str)
def foo(self, some_tring):
    print ("Some string: %s" % some_string)

...然后在js文件中(或在index.html中),您只需拨打MyChannel.foo('whatever')即可。您可以将其作为onclick执行,或者您可以从onclick调用的另一个函数的主体执行此操作。

通过MyChannel.foo('whatever')进行交谈:您调用MyChannel,因为这是您为通道注册的对象(在python中)指定的名称,以及您在创建{时在js中使用的名称{1}}。创建注册时,您将new QWebChannel作为要注册的对象传递 - 因此由self标识的频道是您的MyChannel对象。你只能通过频道发出信号,所以你“呼叫”的任何东西都必须是一个插槽 - 因此装饰者。

或者,如果你想从PyQt调用一个js函数,它会更容易一些。在这种情况下,您只需致电

Render

如果您需要对此做出响应,因为它被称为异步,您需要设置响应处理程序:

self.page().runJavaScript('someJsFunction("whatever");')

...然后定义回调(可能是Render的成员):

self.page().runJavaScript('someJsFunction("whatever");', self.__callback)