2014-07-25 131 views
2

我想获取网页的源代码(HTML),例如StackOverflow的主页。Qt - 获取互联网上托管的网页的源代码(HTML代码)

这是我到目前为止编码:

QNetworkAccessManager manager; 
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url))); 

QString html = response->readAll(); // Source should be stored here 

但没有任何反应!当我尝试获取html字符串的值时,它是空的(“”)。

那么,该怎么办?我正在使用Qt 5.3.1。

回答

2

您必须在之间添加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 
+1

这是不好的建议,因为你编写异步代码就好像它是同步的。事实并非如此。如果你没有忘记实际上是'exec()'事件循环,那么你会暴露提交者对'event.exec()'的潜在后果,可能会重新输入这个方法或其他任何方法。由于大多数人并没有在设计时考虑到这些复杂因素,所以我认为它是未定义行为的来源,可能会格式化硬盘驱动器或发起核攻击。显式异步编码在C++ 11和Qt 5的帮助下是一个更和平的选择。 –

+0

那么提交者试图通过同步代码获取HTML,这就是为什么我向他展示这个解决方案。有时候这样做更容易。并感谢您指出我的event.exec()错误。 – MKAROL

+0

是的,我同意将未定义的行为引入您的应用程序很容易。这并不意味着你应该这样做。即使在Qt 4中,Qt也使得异步编码变得相对容易。因为使用C++ 11和Qt 5,建议旋转本地事件循环和类似的疯狂并不存在任何借口。 –

5

QNetworkAccessManager异步工作。您在get()之后立即致电readAll(),但该请求尚未在此时进行。您需要使用QNetworkAccessManager::finished信号,如documentation所示,并将readAll()移动到与此信号相连的插槽。

2

您需要以异步方式对其进行编码。 C++ 11和Qt开始救援。请记住,lambda的主体将在事件循环中稍后执行。

QScopedPointer<QNetworkAccessManager> manager(new QNetworkAccessManager); 
QNetworkReply * response = manager->get(QNetworkRequest(QUrl(url))); 
QObject::connect(manager, &QNetworkAccessManager::finished, [manager, response]{ 
    response->deleteLater(); 
    manager->deleteLater(); 
    if (reponse->error() != QNetworkReply::NoError) return; 
    QString contentType = 
    response->header(QNetworkRequest::ContentTypeHeader).toString(); 
    if (!contentType.contains("charset=utf-8")) { 
    qWarning() << "Content charsets other than utf-8 are not implemented yet."; 
    return; 
    } 
    QString html = QString::fromUtf8(response->readAll()); 
    // do something with the data 
}) && manager.take(); 

除非你只使用该代码一次,你应该把QNetworkManager实例作为控制器类的成员,或者在main

+0

只要询问你的第一条陈述,如果没有NoError,你为什么使用return? – reggie

+0

@reggie_jimac如果发生错误,我将返回(错误状态是* NoError以外的*)。如果出现错误,则可能没有有效的数据,并且进一步的处理毫无意义。 –

+1

调用'deleteLater'后使用对象可以被认为是不好的风格。如果有人在中间添加了导致事件处理的操作,则代码将变得隐含无效。 –