我正在尝试使用 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())
但可惜事实并非如此。该方法打印的所有内容相当于空响应:
<html><head></head><body></body></html>
所以我仔细查看了 setUrl documentation :
The view remains the same until enough data has arrived to display the new url.
这让我觉得可能是在从服务器收到响应之前我太早调用了 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()
最佳答案
复制自 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()
,它可能会起作用。
关于python - 加载网页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27605555/