Qt5获取并解析中国天气网数据

天气查询 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(三级地区) 101010100
比如,北京市海淀区是 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,你学会了吗?

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿基米东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值