简体   繁体   中英

How to keep python qtwebkit instance running and persistent?

I need my Python QtWebKit script to stay running and listen for further commands. Right now, if a user connects and sends a command to the server, the server side script will just run and exit once completed.

For example, if the user enters in a URL to navigate to, QtWebKit fetches the URL and renders it. At some point down the road, they may wish to send a login command and view the screenshot of that page. The script begins, navigates to the URL and logs in, and takes the screenshot of that page.

Is there any way to keep the script to listen for future commands without having to start from the beginning?

What is expected: User sends command to server, QtWebKit loads the URL and stays open. The user sends a command to login and take a screenshot, and QtWebKit logs in and takes a screenshot without having to relaunch the script.

The special case here is that the user does not know ahead of time the exact sequence of commands he wishes to execute. So the user can't spell out A to Z and have the script run through it all at once.

I used twisted to setup a simple xmlrpc server as backend, it's persistent and has the task to create new instances of PyQt/PySide based webkit browsers if needed, or to reuse existing ones. A separate frontend webapp which is the "middle-man" between the user and the backend application sends the commands to the twisted xmlrpc server, along with a session_id, by which the twisted server can lookup if the session_id has an already running browser, or need to instantiate a new one. Here's a simple example:

# -*- coding: utf-8 -*-
from pyvirtualdisplay import Display
display = Display(visible=False, size=(1024, 768), color_depth=24)
display.start()

from PySide.QtGui import QApplication
app = QApplication([])
import qt4reactor
qt4reactor.install()

from twisted.web import server
from twisted.web.xmlrpc import XMLRPC
from twisted.internet import defer
from PySide.QtWebKit import QWebView, QWebPage
from PySide.QtNetwork import QNetworkAccessManager, QNetworkRequest
from PySide.QtCore import QUrl, QByteArray


class Browser(object):

    def __init__(self):
        self.network_manager = QNetworkAccessManager()

        self.web_page = QWebPage()
        self.web_page.setNetworkAccessManager(self.network_manager)

        self.web_view = QWebView()
        self.web_view.setPage(self.web_page)
        self.web_view.loadFinished.connect(self._load_finished)

    def _load_finished(self, ok):
        # the page is loaded
        frame = self.web_view.page().mainFrame()
        self.deferred_request.callback(frame.toHtml())

    def _make_request(self, url):
        request = QNetworkRequest()
        request.setUrl(QUrl(url))
        return request

    def perform(self, request_data):
        # say request_data is a dict having keys: 'url', 'post_data'
        self.deferred_request = defer.Deferred()
        request = self._make_request(request_data['url'])
        self.web_view.load(request)

        return self.deferred_request


class TestXMLRPCServer(XMLRPC):

    def __init__(self):
        XMLRPC.__init__(self, allowNone=True)
        self.browser_instances = dict()

    def xmlrpc_open(self, request_data, session_id):
        print session_id, request_data
        try:
            browser = self.browser_instances[session_id]
            print 'using existing instance'
        except KeyError:
            browser = Browser()
            self.browser_instances[session_id] = browser
            print 'new instance created'

        return browser.perform(request_data)


def start_server(port=1234):
    from twisted.internet import reactor
    r = TestXMLRPCServer()
    reactor.listenTCP(port, server.Site(r))
    reactor.run()


if __name__ == '__main__':
    start_server()

And a client just to test the functionality:

# -*- coding: utf-8 -*-
import xmlrpclib

def test_server(port=1234):
    s = xmlrpclib.Server('http://localhost:{0}/'.format(port))
    session_id = 'a1b2c3d4e5f6'
    html = s.open({'url': 'http://www.google.com'}, session_id)
    print unicode(html).encode('utf-8')
    html = s.open({'url': 'http://www.ubuntu.com'}, session_id)
    print unicode(html).encode('utf-8')

    session_id = 'f6e5d4c3b2a1'
    html = s.open({'url': 'http://www.yahoo.com'}, session_id)
    print unicode(html).encode('utf-8')

if __name__ == '__main__':
    test_server()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM