Есть ли способ синхронно вызвать метод toHtml, который является объектом QWebEnginePage?
Я пытаюсь получить HTML-код из объекта QWebEnginePage. Согласно ссылке на Qt, toHtml объекта QWebEnginePage является асинхронным методом, как показано ниже.
Асинхронный метод для извлечения содержимого страницы в виде 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
...
...
Спасибо, что прочитали это.
Всем хорошего дня.
3 ответа
Простой способ получить такое поведение - использовать QEventLoop()
, Объект этого класса предотвращает код, который после exec_()
от того, чтобы быть выполненным, это не означает, что GUI не продолжает работать.
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_())
Здесь другой подход, а также другое поведение по сравнению с
QEventLoop
метод
Вы можете создать подкласс из
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)
Вы можете использовать объект multiprocessing.Connection, созданный в качестве одной стороны метода send multiprocessing.Pipe, в качестве обратного вызова, а затем сразу же использовать другой конец метода 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()