我需要我的Python QtWebKit脚本继续运行并监听更多命令。现在,如果用户连接并向服务器发送命令,服务器端脚本将只运行并在完成后退出。
例如,如果用户输入要导航到的URL,QtWebKit将获取该URL并进行渲染。在某些时候,他们可能希望发送登录命令并查看该页面的屏幕截图。脚本开始,导航到URL并登录,并获取该页面的屏幕截图。
有没有办法让脚本在不必从头开始的情况下监听未来的命令?
预期结果:用户向服务器发送命令,QtWebKit加载URL并保持打开状态。用户发送登录命令并截取屏幕截图,QtWebKit登录并截取屏幕截图,无需重新启动脚本。
这里的特殊情况是用户提前不知道他希望执行的命令的确切顺序。因此,用户无法拼写出A到Z并让脚本一次性完成所有操作。
答案 0 :(得分:1)
我使用twisted来设置一个简单的xmlrpc服务器作为后端,它是持久的,它的任务是根据需要创建基于PyQt / PySide的webkit浏览器的新实例,或重用现有的实例。一个单独的前端webapp是用户和后端应用程序之间的“中间人”,它将命令发送到扭曲的xmlrpc服务器,以及session_id,如果session_id已经运行了浏览器,则扭曲的服务器可以通过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()