2

예를 들어 StackOverflow의 홈페이지와 같은 웹 페이지의 소스 (HTML)를 가져오고 싶습니다.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

등의 main에 컨트롤러 클래스의 구성원으로 QNetworkManager 인스턴스를 넣어, 또는한다 동기 인 것처럼 비동기 코드를 작성합니다. 그렇지 않습니다. 실제로 이벤트 루프를'exec()'하는 것을 잊지 않았다면,이 메소드를 재진입 할 ​​가능성이있는'event.exec()'의 임의의 결과 나 다른 메소드에 대해 묻는 것이다. 대부분의 사람들은 그러한 합병증을 염두에두고 코드를 설계하지 않기 때문에 하드 드라이브를 포맷하거나 핵 공격을 시도 할 때 정의되지 않은 행동의 원인이라고 생각합니다. C++ 11 및 Qt 5의 도움으로 명시 적으로 비동기 코딩이 더 평화로운 대안입니다. –

+0

질문자가 동기식 코드로 HTML을 얻으려고 했으므로 그에게이 솔루션을 보여주었습니다. 때로는 그렇게하는 것이 더 쉽습니다. event.exec() 실수를 지적 해 주셔서 감사합니다. – MKAROL

+0

예, 응용 프로그램에 정의되지 않은 동작을 도입하는 것은 쉽다는 것에 동의합니다. 그것이 당신이해야한다는 것을 의미하지는 않습니다. Qt는 Qt 4에서도 신호/슬롯 덕분에 비동기 코딩을 상대적으로 쉽게 만듭니다. C++ 11 및 Qt 5에서는 회전하는 로컬 이벤트 루프 및 이와 유사한 미루어 짐을 제안하는 것에는 전혀 변명의 여지가 없습니다. –

5

QNetworkAccessManager은 비동기 적으로 작동합니다. get() 바로 뒤에 readAll()으로 전화를 걸었지만 그 순간 요청이 이루어지지 않았습니다. documentation에 표시된대로 QNetworkAccessManager::finished 신호를 사용하고 readAll()을이 신호에 연결된 슬롯으로 이동해야합니다.

2

비동기식으로 코딩해야합니다. C++ 11과 Qt가 구조되었습니다. 람다의 몸체가 이벤트 루프에서 나중에 실행된다는 것을 기억하십시오. 한 번만이 코드를 사용하지 않는 한 당신이있어 이후

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(); 

, 당신은,이 나쁜 조언을

+0

NoError가없는 경우 왜 첫 번째 if 문을 묻는 이유가 무엇입니까? – reggie

+0

@reggie_jimac 오류가있는 경우 (오류 상태가 * NoError가 아닌 경우) 반환됩니다. 오류가있는 경우 유효한 데이터가 없기 때문에 추가 처리가 무의미합니다. –

+1

'deleteLater'를 호출 한 후에 객체를 사용하면 나쁜 스타일로 간주 될 수 있습니다. 누군가가 중간에 이벤트 처리를 야기하는 조작을 추가하면 코드가 내재적으로 유효하지 않게됩니다. –

관련 문제