如何在PyQt中设置多个多线程QWebViews?

0 投票
1 回答
1541 浏览
提问于 2025-04-17 00:05

我正在用Python和PyQt开发一个应用程序,目的是从一系列网址中获取生成的内容,并利用多个线程来处理这些获取到的源代码。我需要同时运行大约十个QWebView。虽然听起来有点荒唐,但当涉及到数百个网址时,使用线程的QWebView比普通的快了三倍以上。


这是我在测试代码时遇到问题的代码...

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并不是一个很有文档支持的话题,所以我非常希望能得到一些帮助,教我如何成功实现这个功能。

1 个回答

4

你的问题和代码有几个问题:

  • 你提到的是 QWebFrame,但实际上你传给工作线程的是 QWebView。因为 QWebView 是一个 QWidget,它属于主线程(也就是图形界面线程),不应该被其他线程修改。
  • 一个 QWebViewQWebFrame 一次只能加载一个网址,所以你不能在多个工作线程之间共享它。
  • QWebFrame.load() 是异步加载数据的,也就是说,调用 load() 后会立即返回,但数据还没有加载完成。你需要等到 loadFinished() 信号发出后才能访问数据。
  • 因为实际的加载是由操作系统的网络层完成的,而 load() 方法不会阻塞,所以根本不需要在单独的线程中运行它。你为什么认为这样会更快呢?这没道理。
  • 既然你想并行加载数百个网址(或者大约10个,你在同一句话中提到这两者),你确定要使用 QWebFrame 吗?它是一个 展示 类。你真的想渲染HTML,还是只是对获取的数据感兴趣?

撰写回答