为啥在某些网站上多次调用 QWebView.loadFinished,例如YouTube?

Posted

技术标签:

【中文标题】为啥在某些网站上多次调用 QWebView.loadFinished,例如YouTube?【英文标题】:Why is QWebView.loadFinished called several times on some sites e.g. youtube?为什么在某些网站上多次调用 QWebView.loadFinished,例如YouTube? 【发布时间】:2012-01-08 03:25:51 【问题描述】:

根据文档,只有在所有页面元素完成加载后才应发出 loadFinished。这应该意味着它只会被调用一次,但是我注意到在 youtube.com 等一些网站上,它会被调用两次?有没有其他方法可以绕过这个bug 或者检测 page.load 事件的最可靠方法是什么?

这是测试代码:

import sys
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtCore import QUrl
from PyQt4.QtGui import QApplication

def onDone(val):
    print "Done ...",val

def onStart():
    print "Started..."   

app = QApplication(sys.argv)
ui =  QtWebKit.QWebView()
ui.loadStarted.connect(onStart)
ui.loadFinished.connect(onDone)

ui.load(QUrl("http://www.youtube.com"))   
ui.showMaximized()
sys.exit(app.exec_())

输出:

Started...
Done ... True
Started...
Done ... True

编辑: 有一个几乎相同的question,但它已经超过 2 年了,仍然没有得到答复。

【问题讨论】:

我很确定当你修改 DOM 时会发生这种情况,就像它是一个字符串一样。 我已经发布了代码。 DOM 是如何被修改的?它的简单 url 加载,不是吗?? 我确信 QWebKit 运行的是 JS 代码,所以它可以在 onDone() 之后修改 DOM。这是评论而不是答案。 同意。你说的是真的。当我禁用 javascript 时,它运行良好。所以我应该只处理第一次调用并忽略后续调用 - 这是处理的正确方法还是有更好的选择? 【参考方案1】:

每加载一帧,load* 信号就会触发一次。

要仅捕获第一组信号,请连接到主机的相应信号:

ui.page().mainFrame().loadStarted.connect(onStart)
ui.page().mainFrame().loadFinished.connect(onDone)

您可以通过连接到frameCreated 信号来验证是否正在加载其他帧,该信号将为在主帧加载后创建的每个后续帧触发一次:

def onFrame(val):
    print 'Frame Created:', val.frameName()

ui.page().frameCreated.connect(onFrame)

【讨论】:

感谢您的回答。但是有一个疑问(不在系统中,所以无法检查自己) - QWebFrame 是否会持续超过渲染页面的生命周期?我的印象是为站点的每个框架创建一个框架,并且一旦加载下一页就应该将其销毁。请原谅我缺乏洞察力,但我对 qt 很陌生。 @Codefreak。如果您在加载新页面之前询问是否需要断开并重新连接信号,答案是:不需要。还要注意,无论网页是否有任何<frame><iframe> 标签,总是有一个mainFrame 对象。 是的,这正是我想知道的。感谢您的信息。 @ekhumoro 我还是不明白,如何检测所有帧都已加载,然后我才会截图? @holms。我不会说没有机会。我的直觉是解决 general 的情况会非常困难,但如果您愿意施加限制(例如递归深度),那么实际的解决方法应该是可能的。在我的脑海中,我不知道该怎么做,但肯定有其他人以前看过这个问题。这就是为什么我最初建议您应该提出一个新问题 - 以这种方式获得答案的机会要大得多(即更多人会关注它)。【参考方案2】:

我很确定当你修改 DOM 时会发生这种情况,就像它是一个字符串一样。我确信 QWebKit 运行的是 JS 代码,所以它可以在 onDone() 之后修改 DOM。

您可能应该创建一个只触发一次的 onDoneFirst 方法。

【讨论】:

我会等待 24 小时以获得更好的答案。如果我没有得到任何答案,我会接受你的答案。 如果稍后发布更好的答案,您可以更改已接受的答案。如果答案有帮助,我们鼓励您投票。请参考***.com/privileges/vote-up和***.com/privileges/create-posts

以上是关于为啥在某些网站上多次调用 QWebView.loadFinished,例如YouTube?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在页面渲染过程中会多次调用 [ngStyle]?

为啥在循环内调用 publishProgress 并多次调用(没有循环)会显示不同的行为?

为啥 componentDidMount 在 react.js 和 redux 中被多次调用?

android - 为啥在 Horizo​​ntalPager.OnScrollListener() 接口中多次调用 onViewScrollFinished

为啥保守光栅化无法为某些三角形调用片段着色器?

为啥 ContentObserver 会被多次调用?