Получение нескольких сигналов loadFinished для запрошенной веб-страницы

Я получаю несколько сигналов loadFinished, когда пытаюсь загрузить QWebPage, и я не уверен, что вызывает проблему. Было несколько других вопросов, которые, казалось, ссылались на ту же проблему, но решения не сработали для меня:

В первом вопросе ответ был "подключать сигналы к слотам только один раз", но я это уже делаю. Ответ на второй вопрос предполагает, что я должен подключаться к сигналу 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 секунды, поэтому я придумал обходной путь: я установил событие таймера, чтобы сигнализировать UA::loadFinished через 3 секунды после получения первого сигнала loadFinished от QWebPage. Это не очень красиво и неэффективно, но в данной ситуации работает.


person Kiril    schedule 08.02.2013    source источник


Ответы (2)


Цитирование документации QWebPage:

Наконец, сигнал loadFinished() выдается, когда содержимое страницы загружено полностью, независимо от выполнения скрипта или рендеринга страницы.

Загвоздка в последней фразе. Итак, некоторые люди в следующей теме указывают на проблему, которую я считаю.

Почему QWebView.loadFinished вызывается несколько раз на некоторых сайтах например ютуб?

Я изо всех сил пытался закодировать сканер, который включает страницы, загружающие контент с использованием javascript за кулисами. Множественная loadFinished - это проблема (я бы хотел, чтобы она срабатывала после того, как все успокоилось), но я заметил, что основная проблема заключается в том, что содержимое веб-страницы может по-прежнему не отображаться/подготовлено даже после того, как последняя loadFinished активирует слот.

Поэтому я экспериментировал со многими сигналами класса QWebPage, чтобы увидеть, срабатывают ли какие-либо из них последовательно после сигнала loadFinished.

Найден один: repaintRequested(QRect)

Я не знаю, работает ли это все время. Но если какой-либо контент влияет на внешний вид веб-страницы, я считаю, что этот сигнал должен быть вызван для того, чтобы страница считалась завершенной. Я не отображаю страницы и не использую виджет просмотра, но сигнал постоянно срабатывает. Единственная проблема в том, что он срабатывает много раз. (Намного чаще, чем loadFinished), поэтому вам нужно проверить, совпадает ли mainFrame->requestedUrl() с mainFrame->url(), И существует ли ключевое слово интересующего вас контента. (Особенно, если вы повторно используете веб-страницу, как я. Последующий запрос изменяет запрашиваемый URL-адрес, в то время как содержимое mainFrame из предыдущей загрузки все еще существует. Некоторое постоянство там)

Уловка, позволяющая сократить количество проверяемых сигналов, может заключаться в подключении repaintRequested только после получения сигнала loadFinished от QWebPage (и, возможно, проверки дополнительных условий).

Это может не касаться бесконечных вложенных загрузок, поскольку неизвестно, является ли какой-либо сигнал последним, но если вы ищете контент, то сигнал обязательно будет запущен после загрузки этого конкретного контента (я имею в виду интегрированный в DOM :)

person Onur Ozcan    schedule 22.02.2015

Я решил эту проблему, указав емкость кеша памяти для мертвых объектов, другими словами, я просто отключил кеш памяти QtWebKit, используя:

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

Чтобы узнать больше, вот ссылка

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

person Andres Davila    schedule 27.11.2014