0

URLのリストの生成されたコンテンツを取得し、取得したソースを複数のスレッドの助けを借りて処理できるPyQtを使用して、Pythonでアプリケーションを作成しようとしています。一度に約 10 個の QWebView を実行する必要があります。ばかげているように聞こえるかもしれませんが、何百もの URL に関しては、スレッド化された QWebViews を使用すると、通常の 3 倍以上の速さで結果が得られます。


これが私が問題を抱えていたテストコードです...

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

class Worker(QThread):
    def __init__(self, url, frame):
        QThread.__init__(self)
        self.url = url
        self.frame = frame
    def run(self):
        self.frame.load(QUrl(self.url))
        print len(self.frame.page().mainFrame().toHtml())


app = QApplication(sys.argv)
webFrame = QWebView()

workerList = []
for x in range(1):
    worker = Worker('http://www.google.com', webFrame)
    workerList.append(worker)
for worker in workerList:
    worker.start()

sys.exit(app.exec_())

上記では、メインの QApplication でQWebView初期化して、以下を取得しようとしました。

QObject: Cannot create children for a parent that is in a different thread.

それで、QThreadでQWebViewを初期化しようとしました。しかし、その後、QWebViewはエラーや何も出力せずに変更されずに空白のままになりました。これはおそらくキャッシュ エラーが原因でした。


何かを見逃している、または非常に重要なステップをスキップしているような気がします。PyQt のスレッド化された QWebViews は実際には文書化されたトピックではないため、これをうまく実装する方法について助けていただければ幸いです。

4

1 に答える 1

4

質問とコードには複数の問題があります。

  • あなたはQWebFrameについて話しているが、実際にはQWebViewをワーカーに渡している。これはQWidgetであるため、メイン(GUI)スレッドに属し、他のスレッドによって変更されるべきではありません。
  • 1つのQWebView / QWebFrameは一度に1つのURLしかロードできないため、複数のワーカー間でURLを共有することはできません。
  • QWebFrame.load()はデータを非同期でロードします。つまり、load()の呼び出しはすぐに戻り、読み取るデータはまだありません。データにアクセスする前に、 loadFinished()シグナルが発行されるのを待つ必要があります。
  • 実際の読み込みはオペレーティングシステムのネットワーク層によって行われ、load()メソッドはブロックされないため、そもそも別のスレッドで実行する必要はありません。なぜこれはもっと速いはずだと主張するのですか?それは意味がありません。
  • 数百のURLを並行してロードしたい(または約10、同じ文で両方に言及している)ので、プレゼンテーションクラスであるQWebFrameを使用してもよろしいですか?実際にHTMLをレンダリングしたいですか、それとも取得したデータに興味がありますか?
于 2011-08-22T13:46:31.273 に答える