0

I want render the webpage to an image offscreen, however when I use following code, the output image is blank, I can't solve the problem

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()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
AllenMarz
  • 1
  • 1
  • 1

1 Answers1

0

You must enable the ScreenCaptureEnabled attribute, for this you must first enable the PluginsEnabled attribute. In addition, the content is rendered after using show, but as you do not want to show the widget, we enable the WA_DontShowOnScreen attribute.

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()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I know that this is an old question but I will give it a try: This solution works absolutely fine for "real" webpages but if I use local files (and load them with QUrl.fromLocalFile(self.url)) the result is always a blank page. It seems as if the signal loadFinished is raised to early. – JoergVanAken Feb 05 '19 at 09:45
  • @JoergVanAken what is `self.url`? and show your HTML for testing. – eyllanesc Feb 12 '19 at 00:18
  • Thank you very much for your reply! I should be more precise. `self.url` is something like `r'\C:\Output.html`. The page is rendered correct if I comment out `self.close`. I'm able to produce a png-File if I call the `save` method in `closeEvent` and close the window by hand. But the "automatic" way does not work. – JoergVanAken Feb 12 '19 at 07:54
  • @JoergVanAken try again – eyllanesc Feb 12 '19 at 08:17
  • I'm very sorry, but page.png is still a blank page. – JoergVanAken Feb 12 '19 at 08:37
  • @JoergVanAken well I have tested it and it works correctly so it is probably a bug of the version of PyQt5 that you use or of the platform where you run it – eyllanesc Feb 12 '19 at 08:43
  • Thanks again. I started with a new environment but it still fails. Which version of pyqt do you use? – JoergVanAken Feb 12 '19 at 10:02
  • @JoergVanAken I am using PyQt5 5.11.3 on Linux – eyllanesc Feb 12 '19 at 10:04