4

我正在尝试从 QWebEnginePage 对象获取 html 代码。根据 Qt 参考,QWebEnginePage 对象的“toHtml”是异步方法,如下所示。

将页面内容检索为 HTML 的异步方法,包含在 HTML 和 BODY 标记中。成功完成后,将使用页面内容调用 resultCallback。

所以我试图找出如何同步调用这个方法。

我想要得到的结果如下。

class MainWindow(QWidget):
  html = None
  ...
  ...
  def store_html(self, data):
    self.html = data

  def get_html(self):
    current_page = self.web_view.page()
    current_page.toHtml(self.store_html)
    # I want to wait until the 'store_html' method is finished
    # but the 'toHtml' is called asynchronously, return None when try to return self.html value like below.
    return self.html 
  ...
  ...
4

3 回答 3

4

获得该行为的一种简单方法是使用QEventLoop(). 这个类的一个对象阻止了后面的代码exec_()被执行,这并不意味着 GUI 不会继续工作。

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *


class Widget(QWidget):
    toHtmlFinished = pyqtSignal()

    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        self.web_view = QWebEngineView(self)
        self.web_view.load(QUrl("http://doc.qt.io/qt-5/qeventloop.html"))
        btn = QPushButton("Get HTML", self)
        self.layout().addWidget(self.web_view)
        self.layout().addWidget(btn)
        btn.clicked.connect(self.get_html)
        self.html = ""

    def store_html(self, html):
        self.html = html
        self.toHtmlFinished.emit()

    def get_html(self):
        current_page = self.web_view.page()
        current_page.toHtml(self.store_html)
        loop = QEventLoop()
        self.toHtmlFinished.connect(loop.quit)
        loop.exec_()
        print(self.html)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

注意:相同的方法适用于 PySide2。

于 2017-11-02T04:20:52.100 回答
1

QEventLoop与方法相比,这是一种不同的方法,也是一种不同的行为

您可以使用 Signal 继承QWebEngineView和扩展load()功能loadFinished并创建自定义方法read_html()

class MyWebView(QWebEngineView):

    def __init__(self, parent):
        super(MyWebView, self).__init__(parent)
        self.html = None

    def read_html(self, url):
        """
        Load url and read webpage content in html
        """
        def read_page():
            def process_html(html):
                self.html = html
            self.page().toHtml(process_html)

        self.load(url)
        self.loadFinished.connect(read_page)

这样,在事件循环中等待页面完成加载时应用程序不会停止,但是一旦页面加载完毕,您就可以访问 HTML 内容。

class MainWindow(QWidget):
    def __int__(self):
        ...
        self.web_view = MyWebView(self)
        self.web_view.read_html(r'https://www.xingyulei.com/')
        ...
        self.btn.clicked.connect(self.print_html)

    def print_html(self):
        print(self.view.html)
于 2022-01-30T23:02:24.900 回答
0

您可以使用作为 multiprocessing.Pipe 的 send 方法的一侧创建的 multiprocessing.Connection 对象作为回调,然后立即使用管道的 recv 方法的另一端。Recv 将阻塞,直到收到 html,所以请记住这一点

例子:

from multiprocessing import Pipe

class MainWindow(QWidget):
    def __init__(...):
        ...
        self.from_loopback,self.to_loopback=Pipe(False)

    def get_html(self):
        current_page = self.web_view.page()
        current_page.toHtml(self.to_loopback.send)
        return self.from_loopback.recv() 
于 2018-08-21T19:45:12.957 回答