Получение нескольких сигналов 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, Это не очень красиво и не эффективно, но работает в этой ситуации.

2 ответа

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

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

Подвох это последняя фраза. Поэтому некоторые люди в следующей теме указывают на проблему, которой я верю.

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам