天氣查詢 API 接口
中國天氣網提供 3 個 API 接口,以北京為例:
http://m.weather.com.cn/data/101010100.html
http://weather.com.cn/data/sk/101010100.html
http://weather.com.cn/data/cityinfo/101010100.html
直接通路這 3 個 Web API 即可傳回對應城市的天氣資訊,傳回的是 JSON 格式資料。(第一個通路不了 -’’-)
後面的數字是城市代碼,如果想查詢其他城市的天氣情況,隻需要更換為對應的城市代碼即可。那怎麼知道城市代碼呢?我這裡有一份中國天氣網城市代碼文檔。城市代碼由 9 位數字組成,按照長度可以分為如下四個部分:
比如,北京市海澱區是 101010200,廣州是 101280101,台北是 101340101。
http://weather.com.cn/data/sk/101010100.html 傳回的 JSON 資料:
{
"weatherinfo":
{
"city":"北京",
"cityid":"101010100",
"temp":"27.9",
"WD":"南風",
"WS":"小于3級",
"SD":"28%",
"AP":"1002hPa",
"njd":"暫無實況",
"WSE":"<3",
"time":"17:55",
"sm":"2.1",
"isRadar":"1",
"Radar":"JC_RADAR_AZ9010_JB"
}
}
http://weather.com.cn/data/cityinfo/101010100.html 傳回的 JSON 資料:
{
"weatherinfo":
{
"city":"北京",
"cityid":"101010100",
"temp1":"18℃",
"temp2":"31℃",
"weather":"多雲轉陰",
"img1":"n1.gif",
"img2":"d2.gif",
"ptime":"18:00"
}
}
請求與響應
為友善起見,我們設定一個輸入框擷取城市代碼,設定一個按鈕觸發查詢請求,然後将實時氣溫顯示在下面。
Show the code !
【頭檔案】
#ifndef
#define
#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
namespace Ui {
class MainWidget;
}
class MainWidget : public QWidget
{
Q_OBJECT
public:
explicit MainWidget(QWidget *parent = 0);
~MainWidget();
private slots:
void slotReadyRead();
void downloadFinished();
void replyFinished(QNetworkReply *reply);
void on_pushButton_clicked();
private:
Ui::MainWidget *ui;
QNetworkAccessManager *manager;
QNetworkReply *reply;
};
#endif// MAINWIDGET_H
【源檔案】
#include "mainwidget.h"
#include "ui_mainwidget.h"
#include <QTextCodec>
MainWidget::MainWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainWidget)
{
ui->setupUi(this);
this->setWindowTitle(tr("天氣查詢"));
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}
MainWidget::~MainWidget()
{
delete ui;
}
void MainWidget::on_pushButton_clicked()
{
qDebug() << "clicked";
QNetworkRequest request;
request.setUrl(QUrl(QString("http://weather.com.cn/data/sk/%1.html").arg(ui->lineEdit->text())));
/* Set header */
request.setRawHeader(QByteArray("User-Agent"), QByteArray("Mozilla/5.0"));
/* Auto redirect */
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
reply = manager->get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
void MainWidget::slotReadyRead()
{
qDebug() << "ready";
}
void MainWidget::downloadFinished()
{
qDebug() << "download";
reply->deleteLater();
}
void MainWidget::replyFinished(QNetworkReply *reply)
{
qDebug() << "reply";
/* Get http status code */
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if(statusCode.isValid()) {
qDebug() << "status code:" << statusCode.toInt();
}
QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute);
if(reason.isValid()) {
qDebug() << "reason:" << reason.toString();
}
QNetworkReply::NetworkError err = reply->error();
if(err != QNetworkReply::NoError) {
qDebug() << "Failed:" << reply->errorString();
}
else {
QByteArray bytes = reply->readAll();
QString string = QString::fromUtf8(bytes);
qDebug() << string;
}
}
輸入
101010100
,點選查詢按鈕,可以看到終端列印如下:
需要特别注意的是,由于請求發生重定向,是以一定要加上這行代碼,設定自動跳轉,否則會傳回 302。
/* Auto redirect */
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
解析 JSON 資料
建立函數 parseFromJson 用于讀取、解析 JSON 資料,并在 TextBrowser 中直接顯示出來。
void parseFromJson(const QString &jsonStr);
具體代碼實作如下:
void MainWidget::parseFromJson(const QString &jsonStr)
{
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8(), &err);
if(err.error != QJsonParseError::NoError) {
qDebug() << "Parsed error";
return;
}
QJsonObject obj = doc.object();
if(obj.contains(QLatin1Literal("weatherinfo"))) {
qDebug() << "Parsing";
QJsonObject subObj = obj.value("weatherinfo").toObject();
QString city = subObj["city"].toString();
QString temp = subObj["temp"].toString();
QString WD = subObj["WD"].toString();
QString WS = subObj["WS"].toString();
QString time = subObj["time"].toString();
ui->textBrowser->setText(QString("城市:%1\n氣溫:%2\n風向:%3\n風速:%4\n時間:%5").arg(city).arg(temp).arg(WD).arg(WS).arg(time));
}
}
運作程式,輸入城市代碼,查詢… 如下: