我正在尝试使用PySide的QtWebKit模块加载网页。根据文档(Elements of QWebView; QWebFrame::toHtml()),以下脚本应打印Google搜索页面的HTML:
from PySide import QtCore
from PySide import QtGui
from PySide import QtWebKit
# Needed if we want to display the webpage in a widget.
app = QtGui.QApplication([])
view = QtWebKit.QWebView(None)
view.setUrl(QtCore.QUrl("http://www.google.com/"))
frame = view.page().mainFrame()
print(frame.toHtml())
但唉,事实并非如此。所有打印的方法都是等效的null响应:
<html><head></head><body></body></html>
所以我仔细研究了setUrl documentation:
视图保持不变,直到有足够的数据到达显示新网址。
这让我想到,在从服务器收到响应之前,我可能过早地调用了toHtml()方法。所以我编写了一个覆盖setUrl方法的类,阻塞直到loadFinished信号被触发:
import time
class View(QtWebKit.QWebView):
def __init__(self, *args, **kwargs):
super(View, self).__init__(*args, **kwargs)
self.completed = True
self.loadFinished.connect(self.setCompleted)
def setCompleted(self):
self.completed = True
def setUrl(self, url):
self.completed = False
super(View, self).setUrl(url)
while not self.completed:
time.sleep(0.2)
view = View(None)
view.setUrl(QtCore.QUrl("http://www.google.com/"))
frame = view.page().mainFrame()
print(frame.toHtml())
完全没有任何区别。我在这里缺少什么?
编辑:仅仅获取页面的HTML不是我的最终游戏。这是一个代码的简化示例,它没有像我预期的那样工作。感谢Oleh建议用app.processEvents()
替换time.sleep()答案 0 :(得分:3)
从my other answer复制:
from PySide.QtCore import QObject, QUrl, Slot
from PySide.QtGui import QApplication
from PySide.QtWebKit import QWebPage, QWebSettings
qapp = QApplication([])
def load_source(url):
page = QWebPage()
page.settings().setAttribute(QWebSettings.AutoLoadImages, False)
page.mainFrame().setUrl(QUrl(url))
class State(QObject):
src = None
finished = False
@Slot()
def loaded(self, success=True):
self.finished = True
if self.src is None:
self.src = page.mainFrame().toHtml()
state = State()
# Optional; reacts to DOM ready, which happens before a full load
def js():
page.mainFrame().addToJavaScriptWindowObject('qstate$', state)
page.mainFrame().evaluateJavaScript('''
document.addEventListener('DOMContentLoaded', qstate$.loaded);
''')
page.mainFrame().javaScriptWindowObjectCleared.connect(js)
page.mainFrame().loadFinished.connect(state.loaded)
while not state.finished:
qapp.processEvents()
return state.src
load_source
从URL下载数据,并在WebKit修改后返回HTML。它用它的异步事件包装Qt的事件循环,并且是一个阻塞函数。
但你真的应该想想你在做什么。你真的需要调用引擎并获得修改后的HTML吗?如果您只想下载某些网页的HTML,可以采用更简单的方法。
现在,答案中代码的问题是你不要让Qt做任何事情。没有魔法发生,没有代码在后台运行。 Qt基于一个事件循环,你永远不会让它进入那个循环。这通常是通过调用QApplication.exec_
或解决方法processEvents
来实现的,如我的代码所示。您可以将time.sleep(0.2)
替换为app.processEvents()
,它可能会起作用。