2

我需要我的 Python QtWebKit 脚本来保持运行并监听更多命令。现在,如果用户连接并向服务器发送命令,服务器端脚本将在完成后运行并退出。

例如,如果用户输入要导航到的 URL,QtWebKit 会获取 URL 并呈现它。在某个时候,他们可能希望发送登录命令并查看该页面的屏幕截图。脚本开始,导航到 URL 并登录,然后截取该页面的屏幕截图。

有什么方法可以让脚本监听未来的命令而不必从头开始?

预期:用户向服务器发送命令,QtWebKit 加载 URL 并保持打开状态。用户发送命令登录并截屏,QtWebKit 无需重新启动脚本即可登录并截屏。

这里的特殊情况是用户不提前知道他希望执行的命令的确切顺序。所以用户不能拼出 A 到 Z 并让脚本一次运行。

4

1 回答 1

1

我使用 twisted 来设置一个简单的 xmlrpc 服务器作为后端,它是持久的,并且如果需要,它的任务是创建基于 PyQt/PySide 的 webkit 浏览器的新实例,或者重用现有的。一个单独的前端 web 应用程序是用户和后端应用程序之间的“中间人”,将命令连同 session_id 一起发送到扭曲的 xmlrpc 服务器,如果 session_id 具有已经运行的浏览器,扭曲的服务器可以通过它查找,或者需要实例化一个新的。这是一个简单的例子:

# -*- 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()

还有一个客户只是为了测试功能:

# -*- 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()
于 2012-09-20T12:09:35.357 回答