【问题标题】:Load a web page加载网页
【发布时间】:2015-02-20 17:18:58
【问题描述】:

我正在尝试使用 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

视图保持不变,直到有足够的数据来显示新的 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()

【问题讨论】:

    标签: python qt pyqt pyside qwebview


    【解决方案1】:

    复制自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(),它可能会起作用。

    【讨论】:

    • app.ProcessEvents() 正是我想要的。谢谢!
    猜你喜欢
    • 2018-04-08
    • 2019-09-19
    • 2010-10-09
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多