I need to get a dynamic content, that is being loaded by a ajax js call.
I really don't know how to use PyQt but i was hoping i could do this. The HTML is something like:
<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>`
I can render the page with PyQt using this simple code:
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))
How can i run that 'onclick' and get the content?
This is an old question, but...
To run PyQt functions from javascript:
While there may be numerous ways of doing this, I've solved it by using QWebChannel
, and then calling js functions from your html, then use the web channel to communicate with Qt.
You will need qwebchannel.js
. I got mine from the Qt5 examples directory on my local machine. The same file exists on the web in many places. I'll leave it up to you to find it.
Much of this method is described here: http://doc.qt.io/qt-5/qtwebchannel-javascript.html
In your __init__
, create a web channel:
self.webchannel = QtWebChannel.QWebChannel(self)
then set your webengineview's main page to use the channel, and register the object you want to be shared between PyQt and js:
self.page().setWebChannel(self.webchannel)
self.webchannel.registerObject('MyChannel', self)
In your .js (or the javascript section of your .html), setup the web channel:
var MyChannel = null;
new QWebChannel(qt.webChannelTransport, function(channel) {
MyChannel = channel.objects.MyChannel;
});
(This is where qwebchannel.js
comes into play. Your js or html file must be able to include it. For me, I loaded <script src="scripts/qwebchannel.js"></script>
before doing any other js
Now you're setup to make calls from js to PyQt via the channel, but what can you call? Anything that's decorated as a PyQt slot. So, for example, if, in javascript, you wanted to call a "foo" function in Render that takes a string as an argument, then you would create it (as a member of Render) as such:
@QtCore.pyqtSlot(str)
def foo(self, some_tring):
print ("Some string: %s" % some_string)
...and then in the js file (or in your index.html), you would simply make a call to MyChannel.foo('whatever')
. You could do that as an onclick, or you can do it from the body of another function that you call from onclick.
Talking through MyChannel.foo('whatever')
: You call MyChannel
because that was the name you assigned to the object you registered with the channel (in python), and the name you used in js when you created the new QWebChannel
. When you created the registration, you passed self
as the object to register - so the channel, identified by MyChannel
, is your Render
object. You can only signal through the channel, so anything you "call" must be a slot - hence the decorator.
Alternatively, if you want to call a js function from PyQt, it's a bit easier. In that case, you simply call
self.page().runJavaScript('someJsFunction("whatever");')
If you need to do something with the response from that, because it's called async, you'll need to setup a response handler:
self.page().runJavaScript('someJsFunction("whatever");', self.__callback)
...and then define the callback (likely as a member of Render):
def __callback(self, response):
if response:
print ("Handling JS response: %s", response)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With