通过地址获得经纬度(百度Geocoding API)
1.什么是Geocoding?
Geocoding API 是一类简单的HTTP接口,用于提供从地址到经纬度坐标或者从经纬度坐标到地址的转换服务,用户可以使用C# 、C++、Java等开发语言发送HTTP请求且接收JSON、XML的返回数据。
2.功能介绍
Geocoding API包括地址解析和逆地址解析功能。
- 地理编码:即地址解析,由详细到街道的结构化地址得到百度经纬度信息,且支持名胜古迹、标志性建筑名称直接解析返回百度经纬度。例如:“北京市海淀区中关村南大街27号”地址解析的结果是“lng:116.31985,lat:39.959836”,“百度大厦”地址解析的结果是“lng:116.30815,lat:40.056885”
- 逆地理编码,即逆地址解析,由百度经纬度信息得到结构化地址信息。例如:“lat:31.325152,lng:120.558957”逆地址解析的结果是“江苏省苏州市虎丘区塔园路318号”。
3.如何使用
百度地图Geocoding API是一套免费对外开放的API,无使用次数限制。使用方法:
第一步:申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
第二步,拼写发送http请求的url,注意需使用第一步申请的ak。
第三步,接收http请求返回的数据(支持json和xml格式)。
以下是一个关于地理编码的简单示例。发送一个地址是“百度大厦”的请求,返回该地址对应的地理坐标。发送请求的url如下:
http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=E4805d16520de693a3fe707cdc962045&callback=showLocation
4.java调用测试
package addressToGeoTest; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*; public class GetLatAndLngByBaidu { public static void main(String args[]){ String cnAddress="北京市海淀区上地十街10号";
Map<String,String> map = GetLatAndLngByBaidu.getLatitude(cnAddress);
if(null != map){
System.out.println(cnAddress+" 经度:"+map.get("lng")+" 纬度:"+map.get("lat"));
}
}
/**
* 返回输入地址的经纬度坐标
* lng(经度),lat(纬度)
*/
//1,申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
public static final String AK= "VGqyTtpnqfNxkTkPBG5APrGO";
public static Map<String,String> getLatitude(String address){
try {
address = URLEncoder.encode(address, "UTF-8"); //将地址转换成utf-8的16进制
//2, 拼写发送http请求的url,注意需使用第一步申请的ak。
//3, 接收http请求返回的数据(支持json和xml格式)本次采用json形式
URL resjson = new URL("http://api.map.baidu.com/geocoder/v2/?address="
+ address +"&output=json&ak="+ AK);
BufferedReader in = new BufferedReader(
new InputStreamReader(resjson.openStream()));
String res;
StringBuilder sb = new StringBuilder("");
while((res = in.readLine())!=null){
sb.append(res.trim());
}
in.close();
String str = sb.toString();
//System.out.println("return json:"+str);
Map<String,String> map = null;
if(str!=null){
int lngStart = str.indexOf("lng\":");
int lngEnd = str.indexOf(",\"lat");
int latEnd = str.indexOf("},\"precise");
if(lngStart > 0 && lngEnd > 0 && latEnd > 0){
String lng = str.substring(lngStart+5, lngEnd);
String lat = str.substring(lngEnd+7, latEnd);
map = new HashMap<String,String>();
map.put("lng", lng);
map.put("lat", lat);
return map;
}
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
运行结果:
5.简单应用
期望实现功能:
input.txt存放中文地址
从input.txt中读取中文地址,获得经纬度
将中文地址以及经纬度输出到output.txt中
package addressToGeo; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*; public class GetLatAndLngByBaidu { public static void main(String args[]){ long startTime=System.currentTimeMillis();
String fileSourcePath="F://Essex//AddressToGeo//source//input.txt";
String fileDestPath="F://Essex//AddressToGeo//source//output.txt";
readAddressWriteGeo(fileSourcePath,fileDestPath); }
/**
* 返回输入地址的经纬度坐标
* key lng(经度),lat(纬度)
*/
//1,申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
public static final String AK= "VGqyTtpnqfNxkTkPBG5APrGO";
public static Map<String,String> getLatitude(String address){
try {
address = URLEncoder.encode(address, "UTF-8"); //将地址转换成utf-8的16进制
//2, 拼写发送http请求的url,注意需使用第一步申请的ak。
//3, 接收http请求返回的数据(支持json和xml格式)本次采用json形式
URL resjson = new URL("http://api.map.baidu.com/geocoder/v2/?address="
+ address +"&output=json&ak="+ AK);
BufferedReader in = new BufferedReader(
new InputStreamReader(resjson.openStream()));
String res;
StringBuilder sb = new StringBuilder("");
while((res = in.readLine())!=null){
sb.append(res.trim());
}
in.close();
String str = sb.toString();
//System.out.println("return json:"+str);
Map<String,String> map = null;
if(str!=null){
int lngStart = str.indexOf("lng\":");
int lngEnd = str.indexOf(",\"lat");
int latEnd = str.indexOf("},\"precise");
if(lngStart > 0 && lngEnd > 0 && latEnd > 0){
String lng = str.substring(lngStart+5, lngEnd);
String lat = str.substring(lngEnd+7, latEnd);
map = new HashMap<String,String>();
map.put("lng", lng);
map.put("lat", lat);
return map;
}
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
*void readAddressWriteGeo(String sourceFilePath,String destFilePath) 函数
*功能:从sourceFilePath下读取中文地址,获取经纬度,存放在destFilePath中
* */
public static void readAddressWriteGeo(String sourceFilePath,String destFilePath)
{
long startTime=System.currentTimeMillis();
try
{
System.out.println("读取中文地址...");
String encoding="Unicode";
File fileSource=new File(sourceFilePath);//获得输入句柄
FileInputStream fis=new FileInputStream(fileSource);//创建字节流输入对象
InputStreamReader inStream=new InputStreamReader(fis,encoding);//将字节流转换为字符流,编码格式为Unicode,创建字节流输入对象
BufferedReader input=new BufferedReader(inStream); String outputFilePath=createFile(destFilePath);
File fileDest=new File(outputFilePath);//获得输出文件句柄
FileOutputStream fos=new FileOutputStream(destFilePath);//创建字节流输出对象
OutputStreamWriter outStream=new OutputStreamWriter(fos,encoding);//将字节流转换为字符流,编码格式为Unicode,创建字节流输出对象
BufferedWriter output=new BufferedWriter(outStream); String cnAddress=null;
cnAddress=input.readLine();
System.out.println("通过百度api获取经纬度...");
int count=0;
while(cnAddress!=null)
{
//System.out.println(cnAddress);
Map<String,String> map = GetLatAndLngByBaidu.getLatitude(cnAddress);
if(null != map){
//System.out.println("经度:"+map.get("lng"));
//System.out.println("纬度:"+map.get("lat"));
output.write(map.get("lng")+" "+map.get("lat")+" "+cnAddress+"\r\n");
}
cnAddress=input.readLine();
count++;
}
input.close();
output.close(); System.out.println("获取:"+count+"条经纬度信息");
long endTime=System.currentTimeMillis();
System.out.println("花费时间: "+(endTime-startTime)/1000+"s");
System.out.println("经纬度获取成功!");
}
catch(IOException e)
{
e.printStackTrace();
}
}
//创建新的output.txt文档
public static String createFile(String filePath)
{
File f=new File(filePath);//构造一个路径的句柄
if(f.exists())//如果文件存在则删除,不存在则生成
{
f.delete();
}
else
{
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return f.getPath();
} }
运行测试结果:
6.改进
上面的解决方案使用单线程,数据量小的情况下还可以勉强使用。但是当数据量巨大时,耗时就非常的长(测试使用15000条地址数据差不多用了1小时)。考虑到耗费的时间主要花费在获取经纬度时服务器的响应上,因此考虑使用多线程。
从input.txt读入,然后将地址信息切分为多个数组,为每一个数组开一个线程,转换后统一输出到output.txt
实现代码:
package addressToGeo; import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map; class MyThread extends Thread{
private String[] GpsAdd;
private static String AK = "NXlvvuBhTW1Bd7PaatQvyceV";
private String name = "";
private String[] Addmat = {" "};
private int MatLen=0;
public MyThread(String Name, String[] AddMat){
this.name=Name;
this.Addmat = AddMat;
}
public MyThread(){
}
public String[] getGpsAdd(){
return GpsAdd;
}
public void run(){
MatLen = Addmat.length;
GpsAdd = new String[MatLen];
for(int i=0;i<MatLen;i++){
Map<String,String> map = getLatitude(Addmat[i]);
System.out.println(this.name +": " + map.get("lng") + " " + map.get("lat")+ " " + Addmat[i] );
GpsAdd[i] = map.get("lng") + " " + map.get("lat")+ " " + Addmat[i] +"\n";
}
} public static Map<String,String> getLatitude(String address){ Map<String,String> map = new HashMap<String,String>();
try {
address = URLEncoder.encode(address, "UTF-8");
URL resjson = new URL("http://api.map.baidu.com/geocoder/v2/?address="
+ address +"&output=json&ak="+ AK);
URLConnection uc=resjson.openConnection();
uc.setConnectTimeout(1000*100);
uc.setReadTimeout(1000*100);
BufferedReader in = new BufferedReader(
new InputStreamReader(uc.getInputStream())); String res;
StringBuilder sb = new StringBuilder("");
while((res = in.readLine())!=null){
sb.append(res.trim());
}
in.close();
String str = sb.toString(); if(str!=null){
int lngStart = str.indexOf("lng\":");
int lngEnd = str.indexOf(",\"lat");
int latEnd = str.indexOf("},\"precise");
if(lngStart > 0 && lngEnd > 0 && latEnd > 0){
String lng = str.substring(lngStart+5, lngEnd);
String lat = str.substring(lngEnd+7, latEnd); map.put("lng", lng);
map.put("lat", lat); }
}
}catch (Exception e) {
e.printStackTrace();
}
return map;
}
public static String createFile(String filePath)
{
File f = new File(filePath);
if(f.exists()) {
f.delete();
}
else
{
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return f.getPath();
}
}
package addressToGeo; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*; public class GetLatAndLngByBaidu { private static int NumOfThread = 100;
static String fileSourcePath="F://Essex//AddressToGeoAll//source//input.txt";
static String fileDestPath="F://Essex//AddressToGeoAll//source//output.txt"; public static void main(String args[]) throws InterruptedException, IOException{
long startTime=System.currentTimeMillis();
threadStart(startTime);
}
public static void threadStart(long startTime) throws InterruptedException, IOException
{
System.out.println("start...");
String cnAdd ="";
int cnLen = 0;
cnAdd = readAdd(fileSourcePath);
String[] AddStr = cnAdd.split(",");
cnLen = AddStr.length;
System.out.println("get "+cnLen+" chinese address successful...");
System.out.println("to get longitude and latitude ...");
int MatLen = cnLen/NumOfThread;
String [][] sp=new String[NumOfThread][MatLen];
MyThread [] mt=new MyThread[NumOfThread];
for(int j=0;j<NumOfThread;j++)
{
sp[j]=new String[MatLen];
for(int i=0;i<MatLen;i++)
{
sp[j][i]=AddStr[i+j*MatLen];
}
mt[j]=new MyThread("线程"+j,sp[j]);
mt[j].start();
} for(int j=0;j<NumOfThread;j++)
{
mt[j].join();
}
String[] result;
FileWriter letter = new FileWriter(fileDestPath); for(int j=0;j<NumOfThread;j++)
{
result = mt[j].getGpsAdd();
writeFile(result,letter,MatLen);
} //处理结尾由于不能被100整数引起多余的几个数据
if(NumOfThread*MatLen <= cnLen-1){
String[] LastMat = new String[cnLen-NumOfThread*MatLen];
for(int i =0;i<cnLen-NumOfThread*MatLen;i++){
LastMat[i] = AddStr[NumOfThread*MatLen+i];
}
MyThread LastThread = new MyThread("线程last",LastMat);
LastThread.start();
LastThread.join();
result = LastThread.getGpsAdd();
writeFile(result, letter, cnLen-NumOfThread*MatLen);
}
letter.close();
getExcuteTime(startTime);
} //1,申请ak(即获取密钥),若无百度账号则首先需要注册百度账号。
public static final String AK= "NXlvvuBhTW1Bd7PaatQvyceV";
public static String readAdd(String sourceFilePath){
try{
String encoding="Unicode";
File fileSource=new File(sourceFilePath);//获得输入句柄
FileInputStream fis=new FileInputStream(fileSource);//创建字节流输入对象
InputStreamReader inStream=new InputStreamReader(fis,encoding);//将字节流转换为字符流,编码格式为Unicode,创建字节流输入对象
BufferedReader input=new BufferedReader(inStream); String cnAddress=null;
cnAddress=input.readLine();
StringBuilder sb = new StringBuilder("");
while(cnAddress!=null){
sb.append(cnAddress.trim());
sb.append(",");
cnAddress=input.readLine();
}
String sbStr = sb.toString();
// System.out.println(sb.toString()); //输出所有地址
input.close();
return sbStr;
} catch (IOException e){
e.printStackTrace();
}
return null;
}
public static void getExcuteTime(long startTime)
{
long endTime=System.currentTimeMillis();
long time=endTime-startTime;
System.out.println("take time: "+time/1000+" second");
System.out.println("about "+time/1000/60+" minute");
}
public static void writeFile(String[] result, FileWriter writer, int MatLen) throws IOException{
for(int i = 0;i<MatLen;i++){
writer.write(result[i]);;
}
}
}
7.不足
1,网速不好的情况下,开100个线程会出现 java.net.SocketTimeoutException: connect timed out错误。
虽然使用了uc.setConnectTimeout(10000); uc.setReadTimeout(10000); 但是没有起到效果。(求改进)
2,所有的数据都会放在内存上,当数据量到达千万级别时候,会内存不足。(求改进)
8.引用
http://developer.baidu.com/map/webservice-geocoding.htm
http://www.cnblogs.com/gzggyy/archive/2013/06/21/3148610.html
http://lavasoft.blog.51cto.com/62575/99150
http://www.360doc.com/content/13/0422/09/3776353_280044198.shtml
通过地址获得经纬度(百度Geocoding API)的更多相关文章
- 【地图功能开发系列:二】根据地址名称通过百度地图API查询出坐标
根据地址名称通过百度地图API查询出坐标 百度地图ApiUrl string url = "http://api.map.baidu.com/geocoder?address={0}& ...
- 百度地图地址解析(百度Geocoding API)
1.什么是Geocoding? Geocoding API 是一类简单的HTTP接口,用于提供从地址到经纬度坐标或者从经纬度坐标到地址的转换服务,用户可以使用C# .C++.Java等开发语言发送HT ...
- 利用百度API(js),怎样通过地址获取经纬度
根据经纬度找到具体地址:http://api.map.baidu.com/geocoder?location=纬度,经度&output=输出格式类型&key=用户密钥如:http:// ...
- 百度地图API地点搜索-获取经纬度
分享一下地图上的地点搜索和鼠标点击获取地点经纬度,这些都是地图比较基本和实用的代码,其中还包括了根据用户IP进行地图的显示.改变地图上的鼠标样式.启用滚轮缩放等,算是半入门吧,其他的一些可以自己参考百 ...
- 百度地图API开发指南
简介什么是百度地图API? 百度地图API是一套由JavaScript语言编写的应用程序接口,它能够帮助您在网站中构建功能丰富.交互性强的地图应用.百度地图API包含了构建地图基本功能的各种接口,提供 ...
- (转)百度Map API
转自 http://blog.sina.com.cn/s/blog_6079f38301013sb3.html 一.与地图操作相关的接口哦! (这些接口的开启都是写在执行成功的回调函数那里) map ...
- php用百度地图API进行IP定位和GPS定位
<?php /** * 根据地理坐标获取国家.省份.城市,及周边数据类(利用百度Geocoding API实现) * 百度密钥获取方法:http://lbsyun.baidu.com/apico ...
- 谷歌、腾讯、百度相应API批量获取地理位置坐标信息及其优缺点
目录: 申请ak 批量获取地理位置 目的:通过给定的地理位置名称(如:北京市海淀区上地十街十号),获取经纬度信息. 1.申请ak 以百度Geocoding API为例:http://lbsyun.ba ...
- php用百度地图API进行逆地址解析
<?php /** * 根据地理坐标获取国家.省份.城市,及周边数据类(利用百度Geocoding API实现) * 百度密钥获取方法:http://lbsyun.baidu.com/apico ...
随机推荐
- [DeeplearningAI笔记]改善深层神经网络_深度学习的实用层面1.9_归一化normalization
觉得有用的话,欢迎一起讨论相互学习~Follow Me 1.9 归一化Normaliation 训练神经网络,其中一个加速训练的方法就是归一化输入(normalize inputs). 假设我们有一个 ...
- python3操作redis
redis也被称为缓存 1.redis是一个key-value存储系统,没有ForeignKey和ManyToMany的字段. 2.在redis中创建的数据彼此之间是没有关系的,所以也被称为是非关系型 ...
- ABP官方文档翻译 6.1.2 MVC视图
ASP.NET MVC 视图 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc nuget包集成到MVC视图.你可以如往常一样创建正常的MVC视图. AbpWebView ...
- LANMP系列教程之MySQL编译安装CentOS7环境
以MySQL5.5.33版本为例 1.准备工作: 1.首先准备好源代码包 2.并且确保已安装好 "开发工具" 包组和cmake编译工具 3.确保安装好ncurses-devel ...
- Mybatis使用过程问题总结
Mybatis配置文件 test语句问题 字符串比较问题 示例语句:<if test="isIbatis == 'Y'"></if> 问题:NumberEx ...
- BZOJ 4538: [Hnoi2016]网络 [整体二分]
4538: [Hnoi2016]网络 题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值 考虑二分 整体二分最大权值,如果\(k \in [mid+1, ...
- BZOJ 1396&&2865 识别子串[后缀自动机 线段树]
Description 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: 1.i≤K≤j. 2.子串T只在S中出现过一次. 例如, ...
- 使用tcp+select实现客户端与客户端的通信
使用多路复用实现客户端与客户端进行通信: 原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将newsocketfd存放在同一个结构体中,客户端先给服务器发送数据,然后通过服务器转发给 ...
- 安装RabbitMQ(一)
RabbitMQ简介 RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能.健壮以及可伸缩性出名的 ...
- 高可用的MongoDB集群
1.序言 MongoDB 是一个可扩展的高性能,开源,模式自由,面向文档的数据库. 它使用 C++编写.MongoDB 包含一下特点: l 面向集合的存储:适合存储对象及JSON形式的数据. l ...