Python无头QtWebKit浏览器中多个网页的屏幕截图

Python无头QtWebKit浏览器中多个网页的屏幕截图,python,qt,pyqt4,qtwebkit,Python,Qt,Pyqt4,Qtwebkit,我正在尝试渲染多个网页并截图,但我只能在渲染一个网页时让它工作,因为当我在多个网页上尝试时,程序要么停止运行,永远挂起,要么不处理图像,css和将提取站点的文本并将其放入一个长文本块中。通常情况下,它会挂起来 我用于在内存中呈现网页的代码如下: class Render(QWebPage): def __init__(self, url): self.app = QApplication(sys.argv) QWebPage.__init__(self)

我正在尝试渲染多个网页并截图,但我只能在渲染一个网页时让它工作,因为当我在多个网页上尝试时,程序要么停止运行,永远挂起,要么不处理图像,css和将提取站点的文本并将其放入一个长文本块中。通常情况下,它会挂起来

我用于在内存中呈现网页的代码如下:

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("..")

有人知道为什么会发生这种情况吗?

我假定您正在创建渲染类的多个实例。如果是这种情况,那么您很可能会遇到问题,因为您创建了多个QApplication实例。相反,创建单个QApplication并在所有渲染实例之间共享它

您可能还需要停止使用app.quit(),因为您希望QApplication继续运行。此外,由于app.exec_u3;()在调用quit()之前不会退出,因此您需要创建自己的事件循环。大概是这样的:

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

正如Luke在回答中所描述的那样,我反复考虑,以避免为每个
渲染创建
QApplication
实例

不是最整洁的,但对我来说很有用:

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)

谢谢你们两位。这个答案更完整,所以我接受它。这听起来不适合拍摄快照,因为它不会禁用声音。例如,如果您加载此页面:并希望等待一段时间(例如,以便让评论加载),您将能够听到HTML5视频播放。你怎么能避免呢?@user9379我认为没有一个简单的方法可以做到这一点。。插件的功能超出了Qt的控制范围——插件将直接与操作系统的音频进行通信subsystem@user9379将有特定于平台的方法来重定向来自特定进程的音频,比如OSX上的AudioHijack,Linux和Windows上的Jack有一个用于控制应用程序音量的特定APIsomewhere@dbr我实际上正在尝试为网站快照制作一个高级Qt库,这是我唯一的问题。。。谢谢你的回答!