通过IP反查地理位置获取实时天气数据

**

将客户端IP通过百度智能云反查具体地理位置,再根据中央气象台获取到具体的实时天气数据

**

根据IP反查定位

对于Web项目,可以从请求头中获取到客户端IP地址,为防止多次反向代理,则需获取客户端的真实IP地址

代码如下:

public static String getRemoteIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值,第一个为真实IP。
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

获取到IP地址之后,使用百度智能云提供的免费Api接口定位Ip,获取到具体的地址

局域网IP是不可以的,如127.0.0.1192.168.1.1等都是局域网IP都是不可以的

如新疆的某个IP地址为218.195.219.255

https://qifu-api.baidubce.com/ip/geo/v1/district?ip=218.195.219.255

代码如下:

    public static JSONObject district(String ip) {
        try {
            URL url = new URL("https://qifu-api.baidubce.com/ip/geo/v1/district?ip=" + ip);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder content = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                content.append(inputLine);
            }
            in.close();
            String string = content.toString();
            return JSONObject.parseObject(string);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        return null;
    }

获取到的JSON数据格式如下:

{
    "code": "Success",
    "data": {
        "continent": "亚洲",
        "country": "中国",
        "zipcode": "830000",
        "timezone": "UTC+8",
        "accuracy": "区县",
        "owner": "中国教育网",
        "isp": "中国教育网",
        "source": "数据挖掘",
        "areacode": "CN",
        "adcode": "650103",
        "asnumber": "4538",
        "lat": "43.800855",
        "lng": "87.536048",
        "radius": "19.2187",
        "prov": "新疆维吾尔自治区",
        "city": "乌鲁木齐市",
        "district": "沙依巴克区"
    },
    "charge": true,
    "msg": "查询成功",
    "ip": "218.195.219.255",
    "coordsys": "WGS84"
}

到这一步,解析JSON可以拿到prov(省)、city(市)

获取我国省份信息

这里通过调用中央气象台Api接口获取气象上我国省份信息

http://www.nmc.cn/rest/province

通过浏览器访问可以看到JSON数据格式如下

[
  {
    "code": "ABJ",
    "name": "北京市",
    "url": "/publish/forecast/ABJ.html"
  },
  {
    "code": "ATJ",
    "name": "天津市",
    "url": "/publish/forecast/ATJ.html"
  }
]

根据JSON数据格式可以建立与之对应的对象,通过JAVA代码调用API获取到JSON数据进行封装成一个ProvData类型的List集合对象


@Component
public class MapConstants {

    /**
     * 中国省份
     */
    public static final String[] CHINA_PROVINCES = {"北京市", "天津市", "河北省", "山西省", "内蒙古自治区", "辽宁省", "吉林省",
            "黑龙江省", "上海市", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省", "河南省", "湖北省", "湖南省", "广东省",
            "广西壮族自治区", "海南省", "重庆市", "四川省", "贵州省", "云南省", "西藏自治区", "陕西省", "甘肃省", "青海省",
            "宁夏回族自治区", "新疆维吾尔自治区", "香港特别行政区", "澳门特别行政区", "台湾省",};

    /**
     * 中国天气省份
     */
    public static class ProvData {
        private String code;
        private String name;
        private String url;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }

    public static final List<ProvData> CHINA_PROVINCES_WEATHER;

    static {
        try {
            CHINA_PROVINCES_WEATHER = init();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @PostConstruct
    public static List<ProvData> init() throws IOException {
        URL url = new URL("http://www.nmc.cn/rest/province");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuilder content = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            content.append(inputLine);
        }
        in.close();
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(content.toString(), new TypeReference<List<ProvData>>() {
        });
    }

    /**
     * 中国天气城市
     */
    public static class CityData {
        private String code;
        private String province;
        private String city;
        private String url;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getProvince() {
            return province;
        }

        public void setProvince(String province) {
            this.province = province;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }
}

根据省份信息获取市信息

首先进行省份对比,拿到对应省份的code值

    String code="";
    for(MapConstants.ProvData provData:CHINA_PROVINCES_WEATHER){
        if(provData.getName().equals(prov)){
            code = provData.getCode();
            break;
        }
    }

再根据code值获取省下有哪些市的信息

这里通过调用中央气象台Api接口根据省份信息获取市信息

如新疆的code值为AXJ

http://www.nmc.cn/rest/province/AXJ

通过浏览器访问可以看到JSON数据格式如下

[
  {
    "code": "51463",
    "province": "新疆维吾尔自治区",
    "city": "乌鲁木齐",
    "url": "/publish/forecast/AXJ/wulumuqi.html"
  },
  {
    "code": "51730",
    "province": "新疆维吾尔自治区",
    "city": "阿拉尔",
    "url": "/publish/forecast/AXJ/alaer.html"
  }
]

根据JSON数据格式可以建立与之对应的对象,通过JAVA代码调用API获取到JSON数据进行封装成一个CityData类型的List
集合对象(在上一步骤中代码部分已经创建好了)

    URL url=new URL("http://www.nmc.cn/rest/province/"+code);
    HttpURLConnection con=(HttpURLConnection)url.openConnection();
    con.setRequestMethod("GET");
    BufferedReader in=new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer content=new StringBuffer();
    while((inputLine=in.readLine())!=null){
        content.append(inputLine);
    }
    in.close();
    ObjectMapper objectMapper=new ObjectMapper();
    List<MapConstants.CityData>cityData=objectMapper.readValue(content.toString(),new TypeReference<List<MapConstants.CityData>>(){
    });

根据城市信息获取天气

首先进行城市对比,拿到对应城市的code值

    for(MapConstants.CityData cityDatum:cityData){
        if(city.contains(cityDatum.getCity())){
            code = cityDatum.getCode();
            break;
        }
    }

再根据code值查询该城市的实时天气

这里通过调用中央气象台Api接口根据省份信息获取市信息

如乌鲁木齐的code值为51463

http://www.nmc.cn/f/rest/real/51463

    String weatherUrl="http://www.nmc.cn/f/rest/real/"+code;
    StringBuilder sb=new StringBuilder();//获取拼接读取到的json字符
    try{
        URL u=new URL(weatherUrl);
        URLConnection urlConnection=u.openConnection();
        //字节输入流读取json数据,并将编码格式设置为utf8
        InputStreamReader reader=new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8);
        //字符流读取输入流的数据
        BufferedReader br=new BufferedReader(reader);
        String inputLines;//循环中间量
        while((inputLines=br.readLine())!=null){
            sb.append(inputLines);
        }
        br.close();
        reader.close();
    }catch(IOException e){
        e.printStackTrace();
    }
    //将字符串转换为json对象
    JSONObject json=JSON.parseObject(sb.toString());

这时已经拿到了该城市的实时天气,可以作进一步处理

乌鲁木齐现在的实时天气如下:

{
  "station": {
    "code": "51463",
    "province": "新疆维吾尔自治区",
    "city": "乌鲁木齐",
    "url": "/publish/forecast/AXJ/wulumuqi.html"
  },
  "publish_time": "2023-09-05 22:10",
  "weather": {
    "temperature": 13.1,
    "temperatureDiff": -4.3,
    "airpressure": 9999,
    "humidity": 87,
    "rain": 0,
    "rcomfort": 54,
    "icomfort": -1,
    "info": "多云",
    "img": "1",
    "feelst": 12.4
  },
  "wind": {
    "direct": "9999",
    "degree": 9999,
    "power": "微风",
    "speed": 0.1
  },
  "warn": {
    "alert": "2023年09月04日18时新疆维吾尔自治区气象台发布雷电黄色预警信号",
    "pic": "http://image.nmc.cn/assets/img/alarm/p0012003.png",
    "province": "新疆维吾尔自治区",
    "city": "9999",
    "url": "/publish/alarm/65000041600000_20230904180345.html",
    "issuecontent": "新疆维吾尔自治区气象台2023年9月4日18时2分发布雷电黄色预警信号:目前伊犁州、克拉玛依市、石河子市、乌鲁木齐市、克州、阿克苏地区西部北部、巴州北部等地的局部区域已出现雷电活动,预计今天夜间,上述区域和博州、塔城地区、阿勒泰地区、昌吉州等地的局部区域仍将有雷电活动,局地伴有短时强降水、8级以上雷暴大风、冰雹等强对流天气,请加强防范。",
    "fmeans": "1.政府及相关部门按照职责做好防雷工作;2.密切关注天气,尽量避免户外活动。",
    "signaltype": "雷电",
    "signallevel": "黄色",
    "pic2": "p0012003.png"
  }
}

建议

除了最后一步获取动态获取某市的实时天气以外,前面的数据尽量做好缓冲或者入库处理,能够合理的节省资源浪费和避免对中央气象台的API接口造成负载运行

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值