Как настроить несколько многопоточных QWebView в PyQt?

Я пытаюсь создать приложение на Python с использованием PyQt, которое может извлекать сгенерированное содержимое списка URL-адресов и обрабатывать извлеченный источник с помощью нескольких потоков. Мне нужно запустить около десяти QWebViews одновременно. Как бы нелепо это ни звучало, когда речь идет о сотнях URL-адресов, использование многопотоковых QWebView дает результаты в 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_())

Выше я попытался инициализировать QWebView в основном QApplication только для того, чтобы получить:

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

Затем я попытался инициализировать QWebView в QThread; но затем QWebView оставался неизменным и пустым, не выводя никаких ошибок или чего-либо еще. Вероятно, это произошло из-за ошибки кэша.


Такое ощущение, что я что-то упускаю или пропускаю очень важный шаг. Поскольку потоковые представления QWebView в PyQt не являются действительно задокументированной темой, я был бы очень признателен за любую помощь в том, как это успешно реализовать.


person enderskill    schedule 22.08.2011    source источник


Ответы (1)


Есть несколько проблем с вашим вопросом и кодом:

  • Вы говорите о QWebFrame, но на самом деле передаете QWebView своим рабочим процессам. Поскольку это QWidget, он принадлежит основному (GUI) потоку и не должен изменяться другими потоками.
  • Один QWebView / QWebFrame может одновременно загружать только один URL-адрес, поэтому вы не можете использовать его для нескольких рабочих процессов.
  • QWebFrame.load() загружает данные асинхронно, т. е. вызов load() возвращает результат немедленно, и данных для чтения еще не будет. Вам придется дождаться сигнала loadFinished(), прежде чем вы сможете получить доступ к данным.
  • Поскольку фактическая загрузка выполняется сетевым уровнем операционной системы, а метод load() не блокируется, в первую очередь нет необходимости запускать его в отдельном потоке. Почему вы утверждаете, что это должно быть быстрее - это не имеет смысла.
  • Поскольку вы хотите загружать сотни URL-адресов параллельно (или около 10, вы упоминаете оба в одном предложении), уверены ли вы, что хотите использовать QWebFrame, который является презентацией< /em> класс? Вы действительно хотите отображать HTML или вас просто интересуют полученные данные?
person Ferdinand Beyer    schedule 22.08.2011
comment
Извините, когда я сказал QWebFrame, я имел в виду QWebView. Я отредактировал пост с изменениями. - person enderskill; 22.08.2011
comment
Кроме того, QWebView отображает страницу и и выполняет javascript. Тот факт, что он может выполнять и отображать javascript, абсолютно важен, поскольку это единственная причина, по которой я использую PyQt в первую очередь. Если бы мне просто нужны были данные HTML, я бы просто использовал urllib2 и давно бы покончил с этим. - person enderskill; 22.08.2011
comment
Что ж, похоже, я искал неправильное решение. Как вы сказали, QWebView.load() — это асинхронная функция. Следовательно, это противоречит всей цели использования потоков. Спасибо. - person enderskill; 22.08.2011
comment
так что единственное возможное решение - запустить несколько экземпляров скрипта Python? - person KJW; 21.08.2012