Я получаю несколько 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
, Это не очень красиво и не эффективно, но работает в этой ситуации.
Цитирование документации 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#setObjectCacheCapacities