Qt - Получение исходного кода ( HTML-кода) веб-страницы, размещенной в Интернете
Я хочу получить исходный код (HTML) веб-страницы, например домашней страницы Stackru.
Это то, что я кодировал до сих пор:
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url)));
QString html = response->readAll(); // Source should be stored here
Но ничего не происходит! Когда я пытаюсь получить значение html
строка пуста ("").
Так что делать? Я использую Qt 5.3.1.
4 ответа
Вы должны добавить QEventLoop между.
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url)));
QEventLoop event;
connect(response,SIGNAL(finished()),&event,SLOT(quit()));
event.exec();
QString html = response->readAll(); // Source should be stored here
Вы должны закодировать его асинхронно. C++11 и Qt приходят на помощь. Просто помните, что тело лямбды будет выполняться позже из цикла обработки событий.
// https://github.com/KubaO/stackrun/tree/master/questions/html-get-24965972
#include <QtNetwork>
#include <functional>
void htmlGet(const QUrl &url, const std::function<void(const QString&)> &fun) {
QScopedPointer<QNetworkAccessManager> manager(new QNetworkAccessManager);
QNetworkReply *response = manager->get(QNetworkRequest(QUrl(url)));
QObject::connect(response, &QNetworkReply::finished, [response, fun]{
response->deleteLater();
response->manager()->deleteLater();
if (response->error() != QNetworkReply::NoError) return;
auto const contentType =
response->header(QNetworkRequest::ContentTypeHeader).toString();
static QRegularExpression re("charset=([!-~]+)");
auto const match = re.match(contentType);
if (!match.hasMatch() || 0 != match.captured(1).compare("utf-8", Qt::CaseInsensitive)) {
qWarning() << "Content charsets other than utf-8 are not implemented yet:" << contentType;
return;
}
auto const html = QString::fromUtf8(response->readAll());
fun(html); // do something with the data
}) && manager.take();
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
htmlGet({"http://www.google.com"}, [](const QString &body){ qDebug() << body; qApp->quit(); });
return app.exec();
}
Если вы не используете этот код только один раз, вы должны поставить QNetworkManager
экземпляр как член вашего класса контроллера, или в main
, так далее.
QNetworkAccessManager
работает асинхронно Ты звонишь readAll()
незамедлительно после get()
, но запрос не был сделан в тот момент. Вам нужно использовать QNetworkAccessManager::finished
сигнализировать, как показано в документации и двигаться readAll()
в слот, подключенный к этому сигналу.
Краткий ответ, включающий основную часть в С++17:
const auto manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished,
this, [](auto reply) {
qDebug() << reply->readAll();
});
manager->get(QNetworkRequest({ "https://www.google.com" }));