接收请求的网页的多个loadFinished信号

Receiving multiple loadFinished signals for a requested web page

本文关键字:loadFinished 信号 网页 请求      更新时间:2023-10-16

当我尝试加载QWebPage时,我收到了多个loadFinished信号,我不确定是什么原因导致了问题。还有几个其他问题似乎暗示了同样的问题,但解决方案对我不起作用:

  • 多次调用QtWebPage-loadFinished()
  • 信号QWebPage::loadFinished(bool)返回两次

在第一个问题中,答案是只将信号连接到插槽一次,"但我已经这样做了。第二个问题的答案建议我应该连接到帧的loadFinished信号,但完成后我根本无法获得必要的数据。

我尝试加载多个页面:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);    
    QList<QUrl> urls;
    urls.append(QUrl("http://www.useragentstring.com/pages/Chrome/"));
    urls.append(QUrl("http://www.useragentstring.com/pages/Firefox/"));
    urls.append(QUrl("http://www.useragentstring.com/pages/Opera/"));
    urls.append(QUrl("http://www.useragentstring.com/pages/Internet Explorer/"));
    urls.append(QUrl("http://www.useragentstring.com/pages/Safari/"));
    foreach(QUrl url, urls)
    {
        UA* ua = new UA();
        QWebPage* page = new QWebPage();
        //QObject::connect(page, SIGNAL(loadFinished(bool)), ua, SLOT(pageLoadFinished(bool)));
        QObject::connect(page->mainFrame(), SIGNAL(loadFinished(bool)), ua, SLOT(frameLoadFinished(bool)));
        // Load the page
        page->mainFrame()->load(url);
    }
    return app.exec();
}

处理信号的类如下所示:

class UA:public QObject
{
    Q_OBJECT
private:
    int _numPageLoadSignals;
    int _numFrameLoadSignals
public:
    UA()
    {
        _numPageLoadSignals = 0;
        _numFrameLoadSignals = 0;
    }
    ~UA(){}
public slots:
    void pageLoadFinished(bool ok)
    {
        _numPageLoadSignals++;
        QWebPage * page = qobject_cast<QWebPage *>(sender());
        if(ok && page)
        {    
            qDebug() << _numPageLoadSignals << " loads " 
                << page->mainFrame()->documentElement().findAll("div#liste ul li a").count()
                << " elements found on: " << page->mainFrame()->requestedUrl().toString();
        }
    }
    void frameLoadFinished(bool ok)
    {
        _numFrameLoadSignals++;
        QWebFrame * frame = qobject_cast<QWebFrame *>(sender());
        if(ok && frame)
        {
            qDebug() << _numFrameLoadSignals << " loads " 
                <<  frame->documentElement().findAll("div#liste ul li a").count()
                << " elements found on: " << frame->requestedUrl().toString();
        }
    }
};

以下是仅连接到帧的loadFinished信号的结果:

1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Safari/"
1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Chrome/"
1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Opera/"
1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Firefox/"
1  loads  241  elements found on:  "http://www.useragentstring.com/pages/Internet Explorer/"

以下是当我连接到页面的loadFinished信号时的结果:

1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Safari/"
1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Chrome/"
1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Firefox/"
1  loads  0  elements found on:  "http://www.useragentstring.com/pages/Internet Explorer/"
2  loads  576  elements found on:  "http://www.useragentstring.com/pages/Safari/"
2  loads  782  elements found on:  "http://www.useragentstring.com/pages/Chrome/"
2  loads  241  elements found on:  "http://www.useragentstring.com/pages/Internet Explorer/"
2  loads  1946  elements found on:  "http://www.useragentstring.com/pages/Firefox/"
3  loads  241  elements found on:  "http://www.useragentstring.com/pages/Internet Explorer/"
3  loads  1946  elements found on:  "http://www.useragentstring.com/pages/Firefox/"
3  loads  782  elements found on:  "http://www.useragentstring.com/pages/Chrome/"
1  loads  964  elements found on:  "http://www.useragentstring.com/pages/Opera/"
3  loads  576  elements found on:  "http://www.useragentstring.com/pages/Safari/"

我不理解这种行为,为什么有时我会得到相关的内容,而有时我不会。如果我连接到页面的loadFinished信号,那么我最终会得到内容,但我不知道它什么时候会真正发生我如何知道我的页面何时真正完成加载

更新

我假设我的大部分内容将在不到3秒的时间内到达,所以我想出了一个解决方法:我设置了一个计时器事件,在从QWebPage接收到第一个loadFinished信号后3秒向UA::loadFinished发出信号。这不是很漂亮,也不是很有效,但它适用于这种情况。

引用QWebPage文档:

最后,loadFinished()信号是在页面内容完全加载时发出的,与脚本执行或页面呈现无关。

关键是最后一句话。因此,下面的一些人指出了我认为的问题。

为什么QWebView.loadFinished在一些网站(如youtube)上被多次调用?

我一直在努力编写一个爬网程序,它涉及到在幕后使用javascript加载内容的页面。多个loadFinished是一个问题(我希望在所有事情都解决后触发它。),但我注意到根本问题是,即使在最后一个loadFinish激活了一个插槽后,网页内容可能仍然无法呈现/准备。

因此,我对QWebPage类的许多信号进行了实验,看看它们中是否有任何一个在loadFinished信号之后始终被触发。

找到一个:重新喷漆请求(QRect)

我不知道这是否一直有效。但是,如果任何内容影响了网页的外观,我认为必须调用这个信号才能假设页面是完整的。我既没有显示页面,也没有使用视图小部件,但信号始终被触发。唯一的问题是它被触发了很多次。(比loadFinished频繁得多),因此您需要检查mainFrame->requestedUrl()是否与mainFrame->url()相同,并且您感兴趣的内容的关键字是否存在。(尤其是如果你像我一样重复使用网页。后续请求会更改requestedUrl,而上一次加载的mainFrame内容仍然存在。在那里有一些持久性)

减少要检查的信号数量的一个技巧可能是,只有在从QWebPage接收到loadFinished信号后才连接重新绘制请求(并可能检查额外条件)。

这可能无法解决无限嵌套加载,因为不知道是否有任何信号是最后一个,但如果您正在搜索内容,则在加载特定内容后必然会触发一个信号(我的意思是集成到DOM中:)

我解决了为死对象指定内存缓存容量的问题,换句话说,我只是使用禁用QtWebKit内存缓存

QWebSettings::setObjectCacheCapacities(0, 0, 0);

要了解更多信息,请点击链接

http://qt-project.org/doc/qt-4.8/qwebsettings.html#setObjectCacheCapacities