2014-07-25 127 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'後使用對象可以被認爲是不好的風格。如果有人在中間添加了導致事件處理的操作,則代碼將變得隱含無效。 –