【手把手教你】如何获取中国天气网,获取想要城市的天气-图文并茂-分析代码

35 篇文章 0 订阅
20 篇文章 0 订阅

📚简介:

       这一篇文章的定义已经不是教程篇了,教你如何通过自己的需求来完成功能,有的时候我们会遇到处理一些事情时,我们自己没办法解决,但是可以通过第三方服务解决时一般通过以下方式解决。

通常有3种情况:

  1. 购买第三方的服务,或者入驻开发者。
  2. 自己通过分析第三方服务商接口拿到自己想要的信息
  3. 我们分析不了,大概率只要钱给够,第三方都会提供对应的服务。

💨需求:

    我这里就以之前文章,通过公众号定时推送天气信息给好友为例,其中通过好友设置不同城市,获取不同天气这个案例中,随着日期的改变,天气的情况也会跟着改变,那么就需要通过接口查询天气情况等

完成方式有2个或者更多,我这里就说我了解的几个方案,

  1.      通过入驻开发者获取秘钥信息,调用平台接口获取到值也是比较完善的并且是json格式返回后续不需要过度处理,但是人家为什么给你免费用呀,要不就是有调用的次数或者是超过以后要收费。

在这里插入图片描述

  1. 自己通过分析第三方接口,拿到自己想要的信息。

在这里插入图片描述

🎉自己分析接口:

    对于我来说,写文章我既没有挣到钱,也没有靠软件卖钱,纯纯的技术分享,让小白也可以完成公众号推送天气,并且作为开发者来说,不应该出现玩一玩学习下还要花钱才能完成,我相信还是有很多学生读者朋友们,那么更应该不花钱并且挑战下自己。

在这里插入图片描述

    自己分享下获取中国天气网的数据,既然他要展示那么肯定会请求后端接口,获取城市信息,就算返回的不是json数据我们也可以想办法解析出自己需要的数据。

在这里插入图片描述


     分析接口数据,最好是可以想到网站会在那个页面展示最全的数据信息,这样我们获取到的数据就越多。

点击页面天气信息

在这里插入图片描述

     点击进入可以看到,天气的实时温度,湿度,风速,空气质量等信息,其实后台返回的接口数据不止这些,还有挺多的数据没有被展示出来

在这里插入图片描述

💭分析请求接口:

      在浏览器中按F12,或者右键选择检查会跳出控制台,我们选择网络哪项,我这个是中文的如果你们是英文那应该是Network

在这里插入图片描述

然后分析请求的信息,可以排除png,jpeg类型请求,因为这个类型是图片。

在这里插入图片描述

然后查看请求文件的响应内容,然后查看响应的数据是不是存在有用的

在这里插入图片描述

我什么要叫你们看响应内容是有原因的,有些接口返回的数据在预览里面会出现乱码。

在这里插入图片描述

所以你们可以先看预览如果乱码那么就在看响应里的数据。

🌤️分析出当天天气接口:

我是一个一个请求响应看过去,看到了这个文件有我想要的数据

在这里插入图片描述

请求地址:http://d1.weather.com.cn/dingzhi/101230101.html

在这里插入图片描述

响应数据内容

var cityDZ101230101 ={
    "weatherinfo": {
        "city": "101230101",
        "cityname": "福州",
        "fctime": "202209061100",
        "temp": "34℃",
        "tempn": "25℃",
        "weather": "多云",
        "weathercode": "d1",
        "weathercoden": "n1",
        "wd": "东风转东北风",
        "ws": "<3级"
    }
}
var alarmDZ101230101 ={"w":[]}

     我把内容排版优化下是不是可以看出,我们需要的关键信息,有城市,最高温度,最低温度,天气类型,风速等信息

在这里插入图片描述
     从图中可以看出前面那个接口获取的是当天的天气,并没有包含实况的天气信息,就是左侧展示的数据,那么我们接着查找接口信息。

☁️分析出实况天气接口:

接着往下面找,可以看到预览里面的数据对应这实况数据。那么该接口就是实况天气接口

在这里插入图片描述

请求地址:
http://d1.weather.com.cn/sk_2d/101230101.html

在这里插入图片描述

响应数据内容

var dataSK={
    "nameen": "fuzhou",
    "cityname": "福州",
    "city": "101230101",
    "temp": "27",
    "tempf": "80",
    "WD": "微风",
    "wde": "NWW",
    "WS": "2级",
    "wse": "10km\/h",
    "SD": "63%",
    "sd": "63%",
    "qy": "1003",
    "njd": "24km",
    "time": "17:35",
    "rain": "0",
    "rain24h": "0",
    "aqi": "50",
    "aqi_pm25": "50",
    "weather": "多云",
    "weathere": "Cloudy",
    "weathercode": "d01",
    "limitnumber": "",
    "date": "09月06日(星期二)"
}

我把内容排版优化下是不是可以看出,实况温度,时间,湿度,风速,以及pm2.5的信息


🧐思考问题(关键):

        但是你会发现一个问题他们的请求路径当然是不一样的,我想说的是当天天气请求地址,我没办法通过固定请求返回其他城市的天气,并且没有办法传递城市参数,仔细看接口你会发现这2个接口除了前面路径不一样后面一样都是 101230101.html,但是我当时不知道这个101230101含义是什么,但是可以联想到这个肯定与我查询福州天气有关系。

当天天气请求地址:http://d1.weather.com.cn/dingzhi/101230101.html

实况天气请求地址:
http://d1.weather.com.cn/sk_2d/101230101.html

不知道你们也没有注意到查询的接口中有个city.js的请求
在这里插入图片描述

     查看预览信息,我们可以看到好多城市的信息,并且其中有个AREAID参数,表示城市所在地的标识,并且这个格式和上面的还挺像

在这里插入图片描述

于是我就去响应里面搜索了下福州的101230101标识

在这里插入图片描述

发现存在参数中,所以要想知道我要查询那个城市的提取就必须从该接口中找到AREAID的编号。

城市AREAID请求地址:
https://j.i8tq.com/weather2020/search/city.js

在这里插入图片描述
        但是这个格式是后端特意以这样格式返回前端使用,对于我们来说我们只有把返回的数据按照最下单位获取出来如:

{
    "北京": {
        "北京": {
            "北京": {
                "AREAID": "101010100",
                "NAMECN": "北京"
            },
            "海淀": {
                "AREAID": "101010200",
                "NAMECN": "海淀"
            },
            "朝阳": {
                "AREAID": "101010300",
                "NAMECN": "朝阳"
            },
            "顺义": {
                "AREAID": "101010400",
                "NAMECN": "顺义"
            }
        }
    }
}

这个是省略了一些北京各地点的天气情况,他们都是有层级关系的我们只有获取到最里面那层结构使用
在这里插入图片描述
你们会怎么把该数据提取出来呢?评论区走一波,看看也没有更好的方法。

在这里插入图片描述

我分析了下,该接口的数据他是有层级格式的,按照省>市>区展示

在这里插入图片描述

那既然是三层结构,那我是不是可以提供循环遍历三层,在把最后一层数据保存在一个Map集合中。


🔭验证猜想:

      假设我这已经把城市数据提取到一个Map中,接着我们要查询北京天气,在通过城市名称从Map中获取出对应的AREAID

写代码前,先验证下我们的猜想是否正确。

使用请求工具拼接路径查看请求结果,工具可以是ApiPost,PostMan等工具:

获取实时天气:(北京)

"北京": {
     "AREAID": "101010100",
     "NAMECN": "北京"
 }

可以看出返回了北京的天气,为了验证我们打开天气网查看北京今天天气。
在这里插入图片描述

响应数据:

var dataSK={
    "nameen": "beijing",
    "cityname": "北京",
    "city": "101010100",
    "temp": "28",
    "tempf": "82",
    "WD": "微风",
    "wde": "NWW",
    "WS": "2级",
    "wse": "6km\/h",
    "SD": "25%",
    "sd": "25%",
    "qy": "1014",
    "njd": "30km",
    "time": "10:30",
    "rain": "0",
    "rain24h": "0",
    "aqi": "27",
    "aqi_pm25": "27",
    "weather": "多云",
    "weathere": "Cloudy",
    "weathercode": "d01",
    "limitnumber": "4和9",
    "date": "09月07日(星期三)"
}

在这里插入图片描述
可以看出是一一对应上的,那么另外一个接口我就不测试了。

注意:请求头一定要添加

Referer:http://www.weather.com.cn/这个的作用就是为了防盗链和防止恶意请求
在这里插入图片描述

🎃代码编写:

      编写的案例,使用的是SpringBoot脚手架创建Spring项目。可以查看往期内容的SpringBoot项目创建跳转

配置下application.yml

在这里插入图片描述
创建一个WeatherService

在这里插入图片描述

pom.xml引入坐标

        <!--hutool工具包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.1</version>
        </dependency>

🗺️城市AREAID获取:

我们先把城市的js数据解析出来
城市AREAID请求地址:

https://j.i8tq.com/weather2020/search/city.js

代码:

    public static JSONObject getCity(){
        String cityjs="https://j.i8tq.com/weather2020/search/city.js";
        //发送请求获取数据
        String cityStr = HttpUtil.createGet(cityjs).header("Referer", "http://www.weather.com.cn/").execute().body();
        //需要解析数据
        String cityJson = cityStr.replace("var city_data =", "");
        //创建集合存储数据
        //使用 NAMECN:AREAID
        Map<String, Long> map = new HashMap<>();
        JSONObject entries = JSONUtil.parseObj(cityJson);
        Set<String> keys = entries.keySet();
        for (String key : keys) {
            System.out.println("第一层 省" + key);
            Set<String> citys = entries.getJSONObject(key).keySet();
            for (String city : citys) {
                System.out.println("--第二层 城市" + city);
                Set<String> areas = entries.getJSONObject(key).getJSONObject(city).keySet();
                for (String area : areas) {
                    System.out.println("---第三层 区:" + area);
                    JSONObject jsonObject = entries.getJSONObject(key).getJSONObject(city).getJSONObject(area);
                    System.out.println(jsonObject.toString());
                    map.put(jsonObject.getStr("NAMECN"), jsonObject.getLong("AREAID"));
                }
            }
        }
        //把map数据转换成json
        String jsonStr = JSONUtil.toJsonStr(map);
        System.out.println(jsonStr);
        return JSONUtil.parseObj(map);
    }

运行结果如下:

在这里插入图片描述
可以看出解析出来的数据就是以NAMECN:AREAID格式
在这里插入图片描述

🎢城市实况天气获取:

实况天气请求地址:

http://d1.weather.com.cn/sk_2d/传入城市的AREAID.html

代码:

    public static void main(String[] args) {
        //getCity();
        JSONObject realWeather = getRealWeather("南平");
        System.out.println(realWeather.getStr("cityname")
                +" 天气:"+ realWeather.getStr("weather")
                +" 温度:"+ realWeather.getStr("temp")
                +" 湿度:"+ realWeather.getStr("sd")
                +" Pm2.5:"+realWeather.getStr("aqi_pm25")
        );
    }
    /**
     * 获取实时城市天气
     * @param city
     * @return
     */
    public static JSONObject getRealWeather(String city){
        //获取出所有城市的AreaId
        JSONObject cityAreaId = getCity();
        //取出对应城市的areaid
        String areaId = cityAreaId.getStr(city);
        //实时天气的地址
        String REALWEATHER_URL="http://d1.weather.com.cn/sk_2d/";
        if (areaId==null){
            throw new RuntimeException("该城市找不到AreaId");
        }
        //拼接请求地址
        String uri=REALWEATHER_URL+areaId+".html";
        String res = HttpUtil.createGet(uri).timeout(10000).header("Referer", "http://www.weather.com.cn/").execute().body();
        //替换数据不然会影响json的解析
        String json = res.replace("var dataSK=", "");
        return JSONUtil.parseObj(json);
    }

运行结果如下:

在这里插入图片描述

对比天气网看数据:

在这里插入图片描述

🚀城市当天天气获取:

        这个就给你动手去完成吧,看的在多也没有自己去按照文章思路去分享一遍,这样自己也可以理解,真的就是看再多不如自己敲一遍来的深刻。特别是初学者一定会有很大的帮助。

🏆总结:

       看完这篇文章对于初学者来说,会有些困难,可能你看到后面去,你就不知道我在写些什么,问题不大,看不懂是因为没有理解我为什么要怎么做,你们可以带着自己的疑问去尝试分析一下,可能我这个方案也不是最佳的,但是可以通过需求去分析得到自己需要的结果,使用什么方法不重要,重要的是在这个过程中你收获了什么,你只看到我分析的过程中比较流畅,其实在我不了解,没去研究的情况下大部分的时间是花在分析上,知道原理之后就会明白自己需要如何写代码。
       这篇文章我也是断断续续的写了好几天,可能看到或读的人可能不多,那么我为什么要坚持写,写作的目的不是为了可以得到多少荣誉,更多的是为了自己在未来的路上走的更远,锻炼自己的思维能力,没有人天生就是笨的,只要你肯付出,加倍的付出你总能在某天感谢之前勤奋的自己,共勉

🍥结束:

    到这里分析城市天气到这里就完成了,后续代码会发布gitee上,如果对你有帮助,一键三连,一起加油!!!


  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
获取天气数据需要连接到中国天气的 API 接口。首先需要注册成为开发者,然后获取 API 接口的地址和 API key。然后在 Arduino 中使用 Ethernet 或 Wi-Fi 模块连接到互联,并使用 HTTP GET 请求来获取天气数据。你可以使用 Arduino 的 Ethernet 或 Wi-Fi 库,以及 JSON 解析库来处理响应数据。 以下是一个使用 Arduino 和 Ethernet 模块获取天气数据的简单示例代码: ```cpp #include <SPI.h> #include <Ethernet.h> #include <ArduinoJson.h> byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; IPAddress ip(192, 168, 1, 177); IPAddress server(218, 75, 157, 99); // 中国天气 API 地址 String apiKey = "your_api_key"; // 替换为你的 API Key EthernetClient client; char buffer[1024]; StaticJsonDocument<1024> jsonDoc; void setup() { Ethernet.begin(mac, ip); Serial.begin(9600); delay(1000); } void loop() { if (client.connect(server, 80)) { client.println("GET /api?city=上海&key=" + apiKey + " HTTP/1.1"); client.println("Host: www.weather.com.cn"); client.println("Connection: close"); client.println(); } while (client.connected() && !client.available()); int length = client.readBytesUntil('\n', buffer, sizeof(buffer)); buffer[length] = '\0'; if (strstr(buffer, "200 OK") != NULL) { while (client.connected() && client.available()) { length = client.readBytesUntil('\n', buffer, sizeof(buffer)); buffer[length] = '\0'; if (strstr(buffer, "Content-Length") != NULL) { int contentLength = atoi(strchr(buffer, ':') + 1); client.readBytes(buffer, contentLength); buffer[contentLength] = '\0'; DeserializationError err = deserializeJson(jsonDoc, buffer); if (err) { Serial.print("JSON deserialization failed: "); Serial.println(err.c_str()); } else { JsonObject weatherInfo = jsonDoc["weatherinfo"]; Serial.print("城市:"); Serial.println(weatherInfo["city"]); Serial.print("温度:"); Serial.println(weatherInfo["temp"]); Serial.print("风向:"); Serial.println(weatherInfo["WD"]); Serial.print("风力:"); Serial.println(weatherInfo["WS"]); Serial.print("湿度:"); Serial.println(weatherInfo["SD"]); Serial.print("发布时间:"); Serial.println(weatherInfo["time"]); } } } } else { Serial.println("HTTP request failed"); } client.stop(); delay(60000); // 每隔一分钟获取一次天气数据 } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hi梅

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

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

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

打赏作者

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

抵扣说明:

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

余额充值