Рендеринг PyQt5 с QWebEngineView

Я хочу отобразить веб-страницу на изображении за кадром, однако, когда я использую следующий код, выходное изображение пустое, я не могу решить проблему.

class PageShotter(QWidget):
    def __init__(self,url,parent=None):
        QWidget.__init__(self,parent)
        self.url = url
    def shot(self):
        self.webview = QtWebEngineWidgets.QWebEngineView(self)
        self.webview.load(QtCore.QUrl(self.url))
        webpage = self.webview.page()
        self.webview.setVisible(True)
        self.webview.loadFinished.connect(self.save)
    def save(self,finished):
        if finished:
            size = self.webview.contentsRect()
            print(u"width:%d,hight:%d" % (size.width(), size.height()))            
            img = QtGui.QImage(size.width(), size.height(), QtGui.QImage.Format_ARGB32)
            painter = QtGui.QPainter(img)            
            self.webview.render(painter,QtCore.QPoint())
            painter.end()
            filename = 'page.png'
            if img.save(filename):
                filepath = os.path.join(os.path.dirname(__file__), filename)
                print(u"success:%s" % filepath)
            else:
                print(u"fail")
        else:
            print("Error")


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    shotter = PageShotter(web_site.base_url)
    shotter.shot()
    app.exec()

person AllenMarz    schedule 17.11.2017    source источник


Ответы (1)


Вы должны включить атрибут ScreenCaptureEnabled, для этого необходимо сначала включить атрибут PluginsEnabled. Кроме того, содержимое отображается после использования show, но поскольку вы не хотите показывать виджет, мы включаем атрибут WA_DontShowOnScreen.

import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets

class PageShotter(QtWebEngineWidgets.QWebEngineView):
    def __init__(self, url, parent=None):
        super(PageShotter, self).__init__(parent)
        self.loadFinished.connect(self.save)
        self.url = url
        self.setAttribute(QtCore.Qt.WA_DontShowOnScreen, True)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
        self.show()
        settings = QtWebEngineWidgets.QWebEngineSettings.globalSettings()
        for attr in (QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, 
                     QtWebEngineWidgets.QWebEngineSettings.ScreenCaptureEnabled,):
            settings.setAttribute(attr, True)

    def shot(self):
        if self.size().isNull():
            self.resize(640, 480)
        self.load(QtCore.QUrl.fromLocalFile(self.url))

    @QtCore.pyqtSlot(bool)
    def save(self, finished):
        if finished:
            size = self.contentsRect()
            print(u"width:%d,hight:%d" % (size.width(), size.height()))
            img = QtGui.QImage(size.width(), size.height(), QtGui.QImage.Format_ARGB32)
            painter = QtGui.QPainter(img)
            self.render(painter)
            painter.end()
            filename = 'page.png'
            if img.save(filename):
                filepath = os.path.join(os.path.dirname(__file__), filename)
                print(u"success:%s" % filepath)
            else:
                print(u"fail")
        else:
            print("Error")
        self.close()


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    shotter = PageShotter(r'C:\Output.html')
    shotter.shot()
    app.exec()
person eyllanesc    schedule 17.11.2017
comment
Я знаю, что это старый вопрос, но я попробую: это решение отлично работает для реальных веб-страниц, но если я использую локальные файлы (и загружаю их с помощью QUrl.fromLocalFile(self.url)) результат всегда пустой страница. Кажется, что сигнал loadFinished повышен до раннего. - person JoergVanAken; 05.02.2019
comment
@JoergVanAken что такое self.url? и покажите свой HTML для тестирования. - person eyllanesc; 12.02.2019
comment
Большое спасибо за Ваш ответ! Я должен быть более точным. self.url это что-то вроде r'\C:\Output.html. Страница отображается правильно, если я закомментирую self.close. Я могу создать png-файл, если вызову метод save в closeEvent и закрою окно вручную. Но автоматический способ не работает. - person JoergVanAken; 12.02.2019
comment
@JoergVanAken попробуй еще раз - person eyllanesc; 12.02.2019
comment
Мне очень жаль, но page.png по-прежнему пустая страница. - person JoergVanAken; 12.02.2019
comment
@JoergVanAken хорошо, я протестировал его, и он работает правильно, так что, вероятно, это ошибка версии PyQt5, которую вы используете, или платформы, на которой вы ее запускаете. - person eyllanesc; 12.02.2019
comment
Спасибо еще раз. Я начал с новой среды, но она все еще терпит неудачу. Какую версию pyqt вы используете? - person JoergVanAken; 12.02.2019
comment
@JoergVanAken Я использую PyQt5 5.11.3 в Linux. - person eyllanesc; 12.02.2019