天气查询 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 位数字组成,按照长度可以分为如下四个部分:
101
(
国
家
代
号
)
01
(
省
级
行
政
区
)
01
(
二
级
地
区
)
00
(
三
级
地
区
)
101(国家代号)01(省级行政区)01(二级地区)00(三级地区)
101(国家代号)01(省级行政区)01(二级地区)00(三级地区)
比如,北京市海淀区是 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 MAINWIDGET_H
#define MAINWIDGET_H
#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));
}
}
运行程序,输入城市代码,查询… 如下:
OK,你学会了吗?