4

複数のWebページをレンダリングしてスクリーンショットを撮ろうとしていますが、1つのWebページをレンダリングする場合にのみ機能させることができます。これは、複数のWebページを試してみると、プログラムがトラックで停止して永久にハングするか、何もしないためです。画像、cssを使用して、サイトのテキストを抽出し、1つの長いテキストブロックに配置します。通常、何が起こっているのかはハングします。

私がメモリ内のウェブページをレンダリングするために使用しているコードはこれです:

class Render(QWebPage):
    def __init__(self, url):
        self.app = QApplication(sys.argv)
        QWebPage.__init__(self)

        # Settings
        s = self.settings()
        #s.setAttribute(QWebSettings.AutoLoadImages, False)
        s.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
        s.setAttribute(QWebSettings.PluginsEnabled, True)

        self.loadFinished.connect(self._loadFinished)
        self.mainFrame().load(QUrl(url))
        #self.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
        self.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
        self.app.exec_()

    def _loadFinished(self, result):
        self.frame = self.mainFrame()
        size = self.frame.contentsSize()
        size.setWidth(1366)
        self.setViewportSize(size)
        self.app.quit()

そして、これが私が画像を保存する方法です:

def run(url):
    os.chdir("output")

    r = Render(url)
    image = QImage(r.viewportSize(), QImage.Format_ARGB32)
    painter = QPainter(image)
    r.frame.render(painter)
    painter.end()
    fp = "%s.png" % os_safe_name(url)
    image.save(fp)
    os.chdir("..")

なぜこれが起こっているのか誰もが知っていますか?

4

2 に答える 2

4

ルークの答えで説明されているように、私QApplicationはそれぞれのインスタンスを作成しないように物事をシャッフルしましたRender

最もきれいではありませんが、私のために働きます:

import re
import sys
import time

# Tested with PySide 1.0.9, changing imports to PyQt should work identically
from PySide.QtCore import Qt, QUrl
from PySide.QtGui import QApplication, QImage, QPainter
from PySide.QtWebKit import QWebPage, QWebSettings


def os_safe_name(url):
    url = re.sub("[^a-zA-Z0-9_-]+", "_", url)
    url = re.sub("_{2,}", "_", url)
    return url


class Render(QWebPage):
    def __init__(self, url):
        QWebPage.__init__(self)

        self.url = url
        self.finished = False

        # Settings
        s = self.settings()
        #s.setAttribute(QWebSettings.AutoLoadImages, False)
        s.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
        s.setAttribute(QWebSettings.PluginsEnabled, True)

        #self.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
        self.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)

        # When page is loaded, callback saves image to file
        self.loadFinished.connect(self._loadFinished)

        self.mainFrame().load(QUrl(url))

    def _loadFinished(self, result):
        frame = self.mainFrame()
        size = frame.contentsSize()
        size.setWidth(1366)
        self.setViewportSize(size)

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

        painter = QPainter(image)
        frame.render(painter)
        painter.end()

        self.filepath = "output/%s.png" % os_safe_name(self.url)
        image.save(self.filepath)

        self.finished = True


def run(url, app = None):
    if app is None:
        app = QApplication(sys.argv)

    r = Render(url)

    while not r.finished:
        app.processEvents()
        time.sleep(0.01)

    return r.filepath


if __name__ == '__main__':
    app = QApplication(sys.argv)

    print run("http://stackoverflow.com", app=app)
    print run("http://google.com", app=app)
于 2012-08-11T16:13:07.800 に答える
1

Renderクラスの複数のインスタンスを作成していると思います。この場合、複数のQApplicationインスタンスを作成するため、問題が発生している可能性があります。代わりに、単一のQApplicationを作成し、それをすべてのRenderインスタンス間で共有します。

また、QApplicationを引き続き機能させたいので、app.quit()の使用を停止する必要があります。さらに、app.exec_()はquit()を呼び出すまで終了しないため、代わりに独自のイベントループを作成する必要があります。このようなもの:

while not self.finished:
    self.app.processEvents()
    time.sleep(0.01)
于 2012-08-11T15:26:08.810 に答える