我正在尝试创建一个可以获取网址列表或单个网址并渲染它们的类。
在列表的情况下,它将它们全部呈现并使包含所有htmls的字典可用。这很好。
在单个案例中,它需要一个url,呈现它并使html作为属性可用,然后退出。当我运行一次时,这可以正常工作,但当我尝试它2次或更多次时,它会在调用app.exec _()时锁定。
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import QWebPage, QWebFrame
class Renderer(QWebPage):
def __init__(self):
self.app = QCoreApplication.instance()
if self.app == None:
self.app = QApplication(sys.argv)
self.app.Type(QApplication.Tty)
QWebPage.__init__(self)
self.pages = []
def start(self, urls):
#for lists
try:
self.loadFinished.disconnect()
except Exception:
pass
self.loadFinished.connect(self.listFinished)
self._urls = iter(urls)
self.fetchNext()
self.app.exec_()
def fetchNext(self):
#for lists
try:
url = next(self._urls)
except StopIteration:
return False
else:
self.mainFrame().load(QUrl(url))
return True
def listFinished(self):
#for lists
html = self.processCurrentPage()
self.pages.append(html)
if not self.fetchNext():
self.app.quit()
def processCurrentPage(self):
url = self.mainFrame().url().toString()
html = self.mainFrame().toHtml()
return html
def render(self, url):
try:
self.loadFinished.disconnect()
except Exception:
pass
self.loadFinished.connect(self.singleFinished)
self._url = url
self.mainFrame().load(QUrl(url))
self.app.exec_()
def singleFinished(self):
print "singleFinished"
html = self.processCurrentPage()
self._html = html
self.app.quit()
我正在尝试做什么?如何修复此代码,以便多次调用render()?我应该只使用基于列表的版本吗?
当我尝试列表情况然后单个案例时,会出现同样的问题。我很确定它不喜欢我在quit()之后调用exec_(),但我还没有找到任何关于此的文档。
答案 0 :(得分:0)
重新创建或重新使用QApplication
对象有时会导致问题,具体取决于平台和/或正在使用的PyQt / PySide的特定版本。
因此我调整了示例代码,以便它使用本地事件循环,而不是不断地退出并重新启动应用程序事件循环。如果页面没有加载,则本地循环应该在30秒后超时。请注意,原始示例尝试创建控制台应用程序(但使用错误的语法)。但是,渲染Web页面需要一个完整的GUI应用程序(事实上,尝试在我的系统上简单地转储核心)。代码在ArchLinux上使用Python2和Python3与PySide-1.2.4和PyQt-4.12进行了测试(从普通控制台运行)。
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import QWebPage, QWebFrame
# from PyQt4.QtCore import *
# from PyQt4.QtGui import *
# from PyQt4.QtWebKit import QWebPage, QWebFrame
class Renderer(QWebPage):
def __init__(self):
self.app = QApplication.instance()
if self.app is None:
self.app = QApplication(sys.argv)
super(Renderer, self).__init__()
self.mainFrame().loadFinished.connect(self.handleLoadFinished)
self.loop = QEventLoop()
def render(self, urls):
self._urls = iter(urls)
self.fetchNext()
def fetchNext(self):
self.loop.exit(0)
try:
url = next(self._urls)
except StopIteration:
return False
else:
self.mainFrame().load(QUrl(url))
timer = QTimer()
timer.setSingleShot(True)
timer.timeout.connect(lambda: self.loop.exit(1))
timer.start(30000)
if self.loop.exec_() == 1:
print('url load timed out: %s' % url)
return True
def processCurrentPage(self):
url = self.mainFrame().url().toString()
html = self.mainFrame().toHtml()
print('loaded: [%d bytes] %s' % (self.bytesReceived(), url))
def handleLoadFinished(self):
self.processCurrentPage()
self.fetchNext()
if __name__ == '__main__':
r = Renderer()
r.render(['http://en.wikipedia.org/'])
r.render(['http://stackoverflow.com/'])
输出:
$ python2 test.py
loaded: [863822 bytes] http://en.wikipedia.org/wiki/Main_Page
loaded: [1718852 bytes] http://stackoverflow.com/