解决Java使用Jsoup后台调用天地图地理编码接口的几个问题

news2024/11/15 8:37:12

目录

前言

一、天地图的地理编码接口

1、相关的API介绍

 2、响应接口

二、使用JSOUP调用相应接口面对的问题及应对

1、第一关访问路径的问题

2、第二关UnsupportedMimeTypeException

3、可能的http获取403问题

三、总结


前言

        如果你现在的项目中有如下的需求,比如已知一个中国境内的地名地址信息,然后需要知道这个地名地址对应的位置信息,比如经纬度信息。要实现上面的需求呢,比如可以通过其它的地图厂商,比如百度地图或者高德地图的开放API接口来实现将文字的地理位置转换为经纬度的位置信息。这是直接调用在线服务的方式,当然我们也可以自己整理基础数据,比如去互联网上搜集别人分享的地名地址信息还有村镇行政区划信息,当有了这些基础的地理数据之后,也可以自己构建私有的地名服务,但是这样需要的信息量是比较大的,也是比较困难的,同时数据的准确性和及时程度都是有一定的延迟的。对基础数据的搜集、清理、存储、检索做成服务化的应用功能。当前在前面的在线服务调用中,可能存在一个服务收费的问题,比如超过了一定的次数就会收费。

        本文分享一种有一定使用次数限制的地理地名地址转换成经纬度的在线服务接口。那就是国家开放的天地图web接口,通过注册成为天地图网站的正式用户,就可以使用它的在线API,虽然面向普通开发者,它也是有一定的次数限制,但是如果我们的量不大,甚至说是一些固定的场景,比如有限的地名地址查找,一天的调用次数是少于3000的,其实是可以满足我们的日常需求的。而且天地图的信息是国家地理中心发布,具有较高的权威性。在之前的一篇Leaflet进行天地图的服务调用的博客中,原文地址:基于天地图使用Leaflet.js进行WebGIS开发实战。博客中讲解的是前端的调用方式,如果我们想将一些地址转换成地理坐标后,还可以保存起来,就需要使用后端服务调用的方式。

        本文即以Java语言为例,我们使用Jsoup作为接口请求工具来访问天地图的地理编码接口。详细讲解在调用天地图的地理编码接口中会遇到的一些艰难险阻,通过解决接口调用过程中的这些问题,掌握如何正确的进行jsoup调用天地图的服务。

一、天地图的地理编码接口

        最开始的时候还是将天地图的地理编码接口给大家介绍一下,让大家有个基本的了解。在天地图的官网上找到地理编码接口,如下图所示:

1、相关的API介绍

        关于天地图的API,我们直接来看官方网站上的介绍,关于请求参数和响应的参数,官网上都定义得比较详细。天地图地理编码API是一类简单的HTTP/HTTPS接口,是指由结构化地址数据(如:北京市海淀区莲花池西路28号)转换为对应坐标点(经纬度)功能,地址解析仅限于国内。 使用地理编码服务前您需要申请Key。

参数值参数说明参数类型是否必备备注(值域)
keyWord请求关键字string

请求: http://api.tianditu.gov.cn/geocoder?ds={"keyWord":"北京市延庆区延庆镇莲花池村前街50夕阳红养老院"}&tk=您的密钥

{
    "location": {
        "lon": "116.001688",
        "level": "地名地址",
        "lat": "40.453228"
    },
    "status": "0",
    "msg": "ok",
    "searchVersion": "4.8.0"
}

 2、响应接口

        在调用了相应的服务接口后,可以看到如上的相应数据。来看一下官网的响应接口参数。

参数值参数说明参数类型备注(值域)
status返回状态string0:正常返回,101:结果为空,404:出错。
msg返回信息stringOK:正常,其他异常。
location地址信息json地址信息

        其中locaction地址信息的对象如下:

参数值参数说明参数类型备注(值域)
lon坐标点显示经度Double必须返回。
lat坐标点显示纬度Double必须返回。
level类别名称string非必须返回。
typeRound附近相似点Array开启周边查询必需返回。

        上面对将要使用的接口进行介绍,方便大家后面在调用时有所了解。下面将结合java语言来重点讲解如何进行接口的调用。

二、使用JSOUP调用相应接口面对的问题及应对

        在了解了天地图的相关接口后,我们即以java开发语言为例,使用Jsoup来进行天地图的接口调用。详细记录在使用Jsoup进行接口访问时遇到的常见问题,以及如何解决上面的问题,正确的获取我们的响应信息,并转换成我们想要的java对象。

1、第一关访问路径的问题

        首先我们在后台按照官方网站的要求,将代码改写成直接请求的方式,具体的代码如下所示:

/**
* 普通请求测试,请求字符串未转义,会报错java.net.MalformedURLException
*/
@Test
public void testSimpleTdtQuery() {
	String address = "长郡梅溪湖中学";
	String queryParams = "ds={'keyWord':'" + address + "'}";
	String url = TDT_ADDRESS_API + queryParams+"'&tk=" + TDT_SERVER_KEY;
	System.out.println(url);
	Document document;
	try {
		document = Jsoup.connect(url).get();
		Elements elements = document.select("body");
		System.out.println(elements.get(0).html().toString());
	} catch (IOException e) {
		e.printStackTrace();
	}
}

        上述代码表示连接天地图的官方接口,接着我们来运行一下,会发现程序报如下的错误:

        错误代码如下,大致的错误:

https://api.tianditu.gov.cn/geocoder?ds={'keyWord':'长郡梅溪湖中学'}'&tk=473af7dc18cafb6b993616a0ce8e1ead
java.net.MalformedURLException: Illegal character in query at index 40: https://api.tianditu.gov.cn/geocoder?ds={'keyWord':'长郡梅溪湖中学'}'&tk=473af7dc18cafb6b993616a0ce8e1ead
	at org.jsoup.helper.CookieUtil.asUri(CookieUtil.java:80)
	at org.jsoup.helper.CookieUtil.applyCookiesToRequest(CookieUtil.java:41)
	at org.jsoup.helper.HttpConnection$Response.createConnection(HttpConnection.java:1033)
	at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:856)
	at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:829)
	at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:366)
	at org.jsoup.helper.HttpConnection.get(HttpConnection.java:353)

        可以看到,这里提示的错误信息是访问的URL有问题,在访问地址的40个字符的位置,就是{}这里,通过提示就大概指导了如何解决。我们将这个花括号进行转义即可。解决的办法很简单,只要将访问的参数地址换成以下的地址即可。

String queryParams = "ds=%7B'keyWord':'" + address + "'%7D";

        修改后再执行就不会再报这个url路径的问题了。

2、第二关UnsupportedMimeTypeException

        在顺利通过第一关的接口访问后,本来是期望可以正常访问到数据的,但是一波未平,一波又起,解决了访问路径的问题,又遇到以下的问题。我们提供访问路径修正后的代码:

/**
* 普通请求测试,未设置忽略content_type,会报错org.jsoup.UnsupportedMimeTypeException
*/
@Test
public void testSimpleTdtQueryWithIgnoreContentType() {
	String address = "长郡梅溪湖中学";
	String queryParams = "ds=%7B'keyWord':'" + address + "'%7D";
	String url = TDT_ADDRESS_API + queryParams+"'&tk=" + TDT_SERVER_KEY;
	System.out.println(url);
	Document document;
	try {
		document = Jsoup.connect(url).get();
		Elements elements = document.select("body");
		System.out.println(elements.get(0).html().toString());
		Gson gson = new Gson();
		TdtAddressInfo info = gson.fromJson(elements.get(0).html().toString(), TdtAddressInfo.class);
		System.out.println(info);
		System.out.println(info.getLocation().getLon());
	} catch (IOException e) {
		e.printStackTrace();
	}
}

        运行后的结果如下所示:

        显示的关键错误信息如下:

https://api.tianditu.gov.cn/geocoder?ds=%7B'keyWord':'长郡梅溪湖中学'%7D'&tk=473af7dc18cafb6b993616a0ce8e1ead
org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/*+xml. Mimetype=application/json; charset=UTF-8, URL=https://api.tianditu.gov.cn/geocoder?ds=%7B'keyWord':'%E9%95%BF%E9%83%A1%E6%A2%85%E6%BA%AA%E6%B9%96%E4%B8%AD%E5%AD%A6'%7D'&tk=473af7dc18cafb6b993616a0ce8e1ead
	at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:900)
	at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:829)
	at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:366)
	at org.jsoup.helper.HttpConnection.get(HttpConnection.java:353)
	at com.yelang.project.education.TestViolationTrainingCase.testSimpleTdtQueryWithUserAgent(TestViolationTrainingCase.java:119)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)

        从上面的提示信息来看,关键的主体信息是org.jsoup.UnsupportedMimeTypeException:Unhandled content type. Must be text/*, application/xml, or application/*+xml. Mimetype=application/json; charset=UTF-8,可以看到是响应的内容类型不受支持。那么这个问题怎么解决呢?

        其实解决办法很简单,在jsoup中,我们可以设置忽略,设置方法如下:

document = Jsoup.connect(url)
					.ignoreContentType(true)
					.get();

        上面的设置就是忽略contenttype,不做任何转换。直接返回字符信息。将响应结果从后台获取后,我们就可以进行数据转换。将json数据转换为java对象。我们来定义对应的java实体类:

package com.yelang.project.education.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class TdtAddressInfo implements Serializable{
	private static final long serialVersionUID = -1013000744231947989L;
	private String msg;//OK:正常,其他异常。
	private String status;//0:正常返回,101:结果为空,404:出错。
	private String searchVersion;//查询版本
	private TdtLocation location;//位置信息
}
package com.yelang.project.education.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class TdtLocation implements Serializable{
	private static final long serialVersionUID = 5155681441498287691L;
	private Double lon;//lon	坐标点显示经度	Double	必须返回。
	private Double lat;//lat	坐标点显示纬度	Double	必须返回。
	private String level;//类别名称	string	非必须返回。
	private String typeRound;//附近相似点	Array	开启周边查询必需返回。
	private Double score;//打分
}

         经过转换后的程序运行结果如下:

https://api.tianditu.gov.cn/geocoder?ds=%7B'keyWord':'长郡梅溪湖中学'%7D'&tk=473af7dc18cafb6b993616a0ce8e1ead
{"msg":"ok","location":{"score":81,"level":"兴趣点","lon":"112.870830","lat":"28.192800","keyWord":"长郡梅溪湖中学"},"searchVersion":"6.4.9V","status":"0"}
TdtAddressInfo(msg=ok, status=0, searchVersion=6.4.9V, location=TdtLocation(lon=112.87083, lat=28.1928, level=兴趣点, typeRound=null, score=81.0))
112.87083

         经过上述的编码设置即完成地理编码接口的调用,也返回了相应的地理信息。

3、可能的http获取403问题

        在访问的过程中,如果顺利的话,可能你不会遇到请求403报错的问题。类似于下面的这种错误。

org.jsoup.HttpStatusException: HTTP error fetching URL. Status=403, URL=http://www.example.com
    at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:537)
    at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:493)
    at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:205)
    at org.jsoup.helper.HttpConnection.get(HttpConnection.java:194)
    at com.javacodeexamples.libraries.jsoup.Jsoup403ForbiddenExample.main(Jsoup403ForbiddenExample.java:19)

        如果在实际使用过程当中遇到这种问题,您可以采用下面的方法进行应对。即可设置用户的user-agent来进行解决。

document = Jsoup.connect(url)
						.header("User-Agent", DEFAULT_USER_AGENT)//添加user-agent 可以避免403的报错
						.ignoreContentType(true)//设置忽略可以防止org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml
						.get();
	private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2";
	

        如果遇到上面的问题,按照上面的解决办法来修复即可。

三、总结

        以上就是本文的主要内容, 本文即以Java语言为例,我们使用Jsoup作为接口请求工具来访问天地图的地理编码接口。详细讲解在调用天地图的地理编码接口中会遇到的一些艰难险阻,通过解决接口调用过程中的这些问题,掌握如何正确的进行jsoup调用天地图的服务。行文仓促,难免有很多不足之处,针对不足还肯定各位专家博主批评指正,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2067969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在pytorch中TensorBoard的使用

from torch.utils.tensorboard import SummaryWriter# writer的使用 # 创建实例 writer SummaryWriter("logs") # 存储位置在logs # 使用如下的两种方法 # writer.add_image() # 标量for i in range(100):writer.add_scalar("y x", i, i)writer.close() …

力扣 | 最长公共子序列 | 动态规划 | 最长公共子序列长度、最长公共子序列

文章目录 一、1143. 最长公共子序列二、求最长公共子序列三、变式一、1035. 不相交的线二、1312. 让字符串成为回文串的最少插入次数 一、1143. 最长公共子序列 LeetCode:1143. 最长公共子序列 这是一道典型的二维动态规划问题,甚至面试都能被面到。 这…

机器人开发--Pure Pursuit纯追踪介绍

机器人开发--Pure Pursuit纯追踪介绍 1 介绍1.1 概述1.2 发展历史1.3 EKF vs MPC vs Pure Pursuit1.4 PP 前探距离的影响 2 理解普渡大学--control-algorithms/basic-pure-pursuit准备导入必要的库什么是 Pure Pursuit 控制器?限制如何工作线圆交点线圆交点与边界选…

JUC-Synchronized原理进阶

轻量级锁 轻量级锁的使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。轻量级锁对使用者是透明的,即语法仍然是 synchronized 假设有两个方法同…

机器学习:opencv图像识别--图片专项

目录 前言 一、读取图片 1.安装opencv库 2.读取彩色图片 3.读取灰度图 二、RGB 1.RGB的概念 2.颜色通道: 3.图像表示 4.代码实现单通道图像 三、ROI 1.代码实现 四、图片打码 五、图片组合 六、图片缩放 总结 前言 OpenCV(Open Source C…

Linux:Linux多线程

目录 线程概念 什么是线程 二级页表 线程的优点 线程的缺点 线程异常 线程用途 Linux进程VS线程 进程和线程 进程的多个线程共享 进程和线程的关系 Linux线程控制 POSIX线程库 线程创建 线程等待 线程终止 分离线程 线程ID及进程地址空间布局 线程概念 什么…

【CAN总线测试】——CAN数据链路层测试

从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者,时光不负有心人。 目录 2.1.位时间 2.2.采样点测试 2.3.CAN报文ID和DLC一致性检查 2.4.预期帧接收测试 2.5.非预期帧接收测试 2.6.总线负载率 1.位时间 用例编号 TG2_TC1 测试目…

android aar适配uniapp

最近有商户需要接入我们sdk,但是我们都是android或者ios原生的,直接用又不能用,需要做适配,本文就教你一步步实现android aar适配uniapp。 官方参考教程:开发者须知 | uni小程序SDK 但是官方写的比较繁琐,好…

计算机毕业设计选题推荐-Cosplay论坛系统-Java/Python项目实战

✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

代码随想录训练营day27|455.分发饼干,376.摆动序列,53. 最大子序和

分发饼干 题目 思路:把最大的饼干分给胃口最大的人,所以可以先对两个数组进行排序,然后用双指针从后往前依次比较。如果饼干能成功头尾,就让饼干组的指针往前移 int biscs.size()-1; int ig.size()-1;//小孩组 for(;i>0;i--…

【摆脱被360安全卫士荼毒:使用这2个软件就够了】

保持电脑健康从拒绝使用360安全卫士开始 提示:不使用360安全卫士,电脑更健康 游戏本被360卫士荼毒的差点报废,感觉在使用360安全卫士后,笔记本的散热风扇很暴躁,笔记本经常高温不退,若你也有这样的烦恼&am…

单元格里显示曲线

想要实现的效果如下&#xff1a;表格每一行都有一个曲线 TreeList与GridControl的设置方法类似。 1、先创建控件的数据源&#xff0c;我使用的是DataTable /// <summary>/// 生成一个DataTable/// </summary>/// <returns></returns>public static Da…

【c++】强制类型转化

一、前言 在C语言中新增了四个关键字static_cast、const_cast、reinterpret_cast和dynamic_cast。这四个关键字都是用于强制类型转换的。 新类型的强制转换可以提供更好的控制强制转换过程&#xff0c;允许控制各种不同种类的强制转换。 C中风格是static_cast<type>(c…

进阶SpringBoot之 SpringSecurity(2)用户认证和授权

Spring Security 官网 Spring Security 是针对 Spring 项目的安全框架 也是 Spring Boot 底层安全模块默认的技术选型 它可以实现强大的 Web 安全控制 只需引入 spring-boot-starter-security 模块&#xff0c;进行少量配置&#xff0c;即可实现强大的安全管理 几个重要的…

首款国产“3A”游戏《黑神话:悟空》爆火,背后有哪些AI技术在助力?

近日&#xff0c;沉淀了4年的首款国产“3A”游戏《黑神话悟空》正式在各大游戏交易平台上线。 据市场研究公司VG Insights 周四晚间发布预估数据&#xff0c;《黑神话&#xff1a;悟空》自发售以来&#xff0c;三天内在 Steam 平台的销量已突破 840 万份&#xff0c;好评率超 …

速腾32线激光雷达使用方法

速腾32线激光雷达 12V电源 实体机ubuntu22.04 ROS2-humble 一、软件安装 mkdir robosense_ws cd robosense_wsmkdir src && cd src/ git clone https://github.com/RoboSense-LiDAR/rslidar_msg.git git clone https://github.com/RoboSense-LiDAR/rslidar_sdk.gi…

数学基础(六)

一、分布 正态分布 二项式分布 均匀分布 卡方分布 二、核函数 核函数的目的&#xff1a; 将低维数据转换为高维数据 线性核函数&#xff1a; Linear核函数对数据不做任何变换 当特征已经比较丰富了&#xff0c;样本数据量巨大&#xff0c;需要进行实时得出结果时进行使用…

【GH】【EXCEL】P3: Set Conditional Formatting To Excel Data By Gh

文章目录 conditional formattingdata sourceConditional ScaleConditional Scale Conditional PercentConditional Top Percent Conditional AverageConditional Average Multiple ConditionsConditional BarConditional Bar Conditional UniqueConditional Unique Conditiona…

JUC7-共享模型之工具

线程池 自定义线程池 import lombok.extern.slf4j.Slf4j; import org.springframework.core.log.LogDelegateFactory;import java.util.ArrayDeque; import java.util.Deque; import java.util.HashSet; import java.util.concurrent.TimeUnit; import java.util.concurrent.l…

git常用操作合集

1 撤销 1.1 适用场景 如果在git上提交了commit&#xff0c;但是当前提交的代码有问题&#xff0c;需要回退到上个版本 1.2 操作命令 1、git log 查看历史提交记录及对应的commit id 找到需要回退的commit id 2、执行git reset回退到之前的状态 git reset --hard <commi…