百度地图逆地理编码api使用/Java实现

        最近有个需求就是个根据GPS信息获得某个地方的详细信息(以街道为例, 其他属性可以见官方文档参数说明逆地理编码 rgc 反geo检索 | 百度地图API SDK),参考一些资料只有Java能跑通就用Java实现了(python会更简单),在以前的参考资料都是v2版本的接口,而现在能申请到的接口都是v3版本的接口,这个接口必须指定服务器IP或者使用SN码校验和进行请求,所以很多教程没法直接使用,这里我选择的是SN码验证。

        申请百度地图开发者之后在控制台创建应用选择sn码校验后你可以获取自己的ak和sk,作为个人开发者每天有5000次的免费额度。

        下面是获取对应经纬度街道信息的主方法,你需要替换自己的ak,由于我需要跑大量数据,在测试中经常会报超过最大并发量的错误,所以某些记录返回值可能是未知。

 /**
     * 根据给的经纬度获取对应地点的街道信息,你需要替换自己的ak,sk才能使用
     * @param lng   纬度
     * @param lat   经度
     * @return      对应街道(路)名称
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    public static String getAdressDetail(double lng,double lat) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String result = "";// 访问返回结果
        BufferedReader read = null;// 读取访问结果
        String street = "";//城镇名称
        String regionScope = "";//城镇范围

        String url = "http://api.map.baidu.com/reverse_geocoding/v3/";
        String param = "ak=替换为自己的ak"+
                "&location="+lng+","+lat + "&output=json" + "&sn=" + getSn("ak", "替换为自己的ak",
                "output", "json",
                "coordtype", "wgs84ll",
                "location", lng+","+lat
                );
//        "extensions_town", "true", &extensions_town=true"
        System.out.println("访问地址:" + url + "?" + param);
        try {
            // 创建url
            URL realurl = new URL(url + "?" + param);
            // 打开连接
            HttpURLConnection connection = (HttpURLConnection)realurl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立连接
            connection.connect();
            // 获取所有响应头字段
			Map<String, List<String>> map = connection.getHeaderFields();
			// 遍历所有的响应头字段,获取到cookies等
			for (String key : map.keySet()) {
				System.out.println(key + "--->" + map.get(key));
			}
            // 定义 BufferedReader输入流来读取URL的响应
            read = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;// 循环读取
            while ((line = read.readLine()) != null) {
                result += line;
            }

//            System.out.println("............................" + connection.getResponseCode());
            //不为空,解析处城镇名称
            if(!"".equals(result)){
                JSONObject jsonInfo = JSONObject.parseObject(result);
                if(!result.equals("{\"status\":401,\"message\":\"当前并发量已经超过约定并发配额,限制访问\"}")) {
                    street = JSONObject.parseObject(JSONObject.parseObject(jsonInfo.getString("result")).getString("addressComponent")).getString("street").toString();
                    regionScope = JSONObject.parseObject(jsonInfo.getString("result")).getString("formatted_address")+street;
                    System.out.println(regionScope);
                }else {
                    street = "查询失败";
                }

            }
            connection.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (read != null) {// 关闭流
                try {
                    read.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }

        }
        return street;
    }

官方文档中获取sn码的方法只对正向编码是正确的,而逆地理编码中由于location参数中间存在逗号‘,’,所以会出现sn码校验失败的错误。

                           ​​​​​​​        

 修改后的sn获取方法如下

/**
     * 获取url的Sn,你需要替换自己的sk才能使用
     * @param paras 可变参数,对应url后的参数,参数为如?location=23.453342,113.453422,则需传入两个参数:“location”, “23.453342,113.453422”
     * @return sn值
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    public static String getSn(String ...paras) throws UnsupportedEncodingException, {

// 计算sn跟参数对出现顺序有关,get请求请使用LinkedHashMap保存<key,value>,该方法根据key的插入顺序排序;post请使用TreeMap保存<key,value>,该方法会自动将key按照字母a-z顺序排序。所以get请求可自定义参数顺序(sn参数必须在最后)发送请求,但是post请求必须按照字母a-z顺序填充body(sn参数必须在最后)。以get请求为例:http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak,paramsMap中先放入address,再放output,然后放ak,放入顺序必须跟get请求中对应参数的出现顺序保持一致。

        Map paramsMap = new TreeMap<String, String>();
        for(int i = 0; i < paras.length / 2; i++) {
            paramsMap.put(paras[2 * i], paras[2 * i + 1]);
        }
//        paramsMap.put("address", "百度大厦");
//        paramsMap.put("output", "json");
//        paramsMap.put("ak", "yourak");

        // 调用下面的toQueryString方法,对LinkedHashMap内所有value作utf8编码,拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourak
        String paramsStr = toQueryString(paramsMap);

        // 对paramsStr前面拼接上/geocoder/v3/?,后面直接拼接yoursk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourakyoursk
        String wholeStr = new String("/reverse_geocoding/v3/?" + paramsStr + "替换为你的sk");
        System.out.println(wholeStr);

        // 对上面wholeStr再作utf8编码
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");


        // 调用下面的MD5方法得到最后的sn签名7de5a22212ffaa9e326444c75a58f9a0
        return MD5(tempStr);
    }

    // 对Map内所有value作utf8编码,拼接返回结果
    //针对location参数的改进

    public static String toQueryString(Map<?, ?> data)
            throws UnsupportedEncodingException {
        StringBuffer queryString = new StringBuffer();
        for (Entry<?, ?> pair : data.entrySet()) {
            queryString.append(pair.getKey() + "=");
            String ss[] = pair.getValue().toString().split(",");
            if(ss.length>1){
                for(String s:ss){
                    queryString.append(URLEncoder.encode(s,"UTF-8") + ",");
                }
                queryString.deleteCharAt(queryString.length()-1);
                queryString.append("&");
            }
            else{
                queryString.append(URLEncoder.encode((String) pair.getValue(),
                        "UTF-8") + "&");
            }
        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();
    }


    // 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
    public static String MD5(String md5) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest
                    .getInstance("MD5");
            byte[] array = md.digest(md5.getBytes());
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < array.length; ++i) {
                sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100)
                        .substring(1, 3));
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
        }
        return null;
    }

使用浏览器打开查询url查看全部结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值