【问题标题】:PyQt: QImage() returns a 'Null'-ImagePyQt:QImage() 返回一个'Null'-Image
【发布时间】:2016-01-03 19:49:28
【问题描述】:

我需要为我的项目截取网站截图。作为开发语言,我使用 Python 并使用 PyQt 的 Webkit 截屏。下面的脚本是用于捕获网站的代码(它被部分修改,但大部分仍与webscraping.com 的原始代码相同)。

现在我的问题如下:
大多数情况下它可以正常工作,但是有时会发生以下异常。

QPainter::begin: Paint device returned engine == 0, type: QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setBrush: Painter not active
QPainter::pen: Painter not active
QPainter::setPen: Painter not active
QPainter::end: Painter not active, aborted

我已经找到了创建图像的问题

image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) 

此行返回的 QImage 有时为 Null - 我使用 QImage 的 .isNull() 方法检查了这一点。
根据 Qt 文档,如果没有足够的内存来分配新的 QImage,就会发生这种情况,但我仍然有足够的可用内存。
这种行为发生在 Windows 和 linux 上运行时,所以我认为它不应该依赖于某些依赖于操作系统的东西。我是 Qt 和 PyQt 的新手,所以希望有人能帮助我。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import sys
import time

# ############################################################# #
# This script is based on the following script:                 #
# https://webscraping.com/blog/Webpage-screenshots-with-webkit/ #
# ############################################################# #

class Screenshot(QWebView):
    _instance = None

    @staticmethod
    def get_instance():
        # TODO: Add a lock around the if including the creation!
        if Screenshot._instance is None:
            Screenshot._instance = Screenshot()

        return Screenshot._instance

    def __init__(self):
        self.app = QApplication(sys.argv)
        QWebView.__init__(self)
        self._loaded = False
        self.loadFinished.connect(self._loadFinished)

    def capture(self, url, output_file):
        self.load(QUrl(url))
        self.wait_load()
        # set to webpage size
        frame = self.page().mainFrame()
        self.page().setViewportSize(frame.contentsSize())
        # render image
        # creating the image. Here it happens that QImage returns a 'Null'-Image
        image = QImage(self.page().viewportSize(), QImage.Format_ARGB32)
        # check if there's no image allocated
        if image.isNull(): 
            print 'image.isNull() is True'
        if image is None:
            print 'image is None is True'
        painter = QPainter(image)
        frame.render(painter)
        painter.end()
        print 'saving', output_file
        image.save(output_file)

    def wait_load(self, delay=0):
        # process app events until page loaded
        while not self._loaded:
            self.app.processEvents()
            time.sleep(delay)
        self._loaded = False

    def _loadFinished(self, result):
        self._loaded = True

if __name__ == '__main__':
    # a simple way to get the exceptions is to try to create multiple screenshots
    sc = Screenshot()
    for i in range(0, 25):
        sc.capture('http://google.de', str(i) + '.png')

    for i in range(25, 50):
        sc.capture('http://de.wikipedia.org', str(i) + '.png')

【问题讨论】:

    标签: python qt web-scraping pyqt pyqt4


    【解决方案1】:

    好的。我已经进一步追踪了这个问题。在读取创建 QImage 时,QWebPages mainFrame 的 contentSize 似乎有时为 (0, 0)。

    frame = self.page().mainFrame()
    self.page().setViewportSize(frame.contentsSize()) # frame.contentsSize() = (0, 0)
    image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) # so we're creating here an Image with Width: 0 and Height: 0
    

    所以基本上 QImage 似乎是 Null,因为它创建的大小是 (0, 0)。
    这个问题可以通过检查 mainFrames contentsSize 是否为 (0, 0) 来解决。如果是 (0, 0),则需要在 QApplication 上处理未完成的事件,直到设置了新的 contentsSize。我现在正在使用以下代码:

    if frame.contentsSize().width() == 0 or frame.contentsSize().height() == 0:
        print 'ContentsSize = (w: {}, h: {})'.format(frame.contentsSize().width(), frame.contentsSize().height())
        count = 0 # used so we're not starting an infinite loop
        while (frame.contentsSize().width() == 0 or frame.contentsSize().height() == 0) and count < 5:
            count += 1
            self.app.processEvents()
            time.sleep(1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-19
      相关资源
      最近更新 更多