做它的原因
接了老师一个项目,老师要我先去收集各个省市县级的边界坐标以及中心城区范围,然后老师要用R语言去画图调用。然后我就直接百度去下载现成的数据,但是老师说不行,要最新的,以前网上的数据都是以前的。现在好多行政区县都已经更新了。近几年的数据还没有。所以只能自己做了。也能确保数据的准确性。
特地强调。确实echarts可以画地图。但是里面的边界数据并不精确。如果你需要做的项目是边界必须特别精确的,而是最新的。你得自己获取。echarts里的china.js数据已经老了。



前期准备
首先我们需要城市信息。哪里来这些城市的信息呢?第一个想到的是百度文科直接下载,第二个是爬虫。但是老师说,还是爬虫好,让我把中国天气预报网上的数据爬下来。那里的城市信息准确。然后我就用八爪鱼爬了(懒得自己写爬虫。。。)。爬下来以后发现。数据不对。天气预报网上的地方确实是最新的。但是天气预备有个特点。相邻区域就不一定会报。比如上海市中心就包含了好几个区。其次用风景区代替城市。导致我查找的地址不准确。做出来画的地图不对。所以,我还是去百度文库里下了一份2016年的省市县级的名称。

不过数据不准确还是得做处理。可以看见,首先,各个省没有分开。意思是我省的数据也是需要的。然后应该纯在省,空,空这样的数据元。还有安庆这里就写了安庆。有些百度是可以直接出来的。但是还有的不行比如巢湖。这个城市你在查找边界范围的时候不输入巢湖市出不来。所以我们需要对这些数据做处理。把省级分开。把名字补全,那些结尾不是区,镇,县,街道,旗(蒙古的比较多)的数据,尾部补上市,便于查找。把重复的给规整,市级是三沙市就是三沙市,县级下面不应该再来个三沙市。
当然这么做还有个前提,要读取excel文件。
我这里采用的是个包pio-3.16。具体方式是参考 http://blog.csdn.net/sinat_29581293/article/details/52122191 它的。
然后展示下,我修改数据的文件

package dealWithSource;import java.io.File;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;import java.io.InputStream;
import java.util.ArrayList;import java.util.List;import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/*** * @描述:测试excel读取* */public class importExcel
{/** 总行数 */private int totalRows= 0;/** 总列数 */private int totalCells= 0;/** 错误信息 */private String errorInfo;/** 构造方法 */public importExcel(){}public int getTotalRows(){return totalRows;}public int getTotalCells(){return totalCells;}public String getErrorInfo(){return errorInfo;}public boolean validateExcel(String filePath){/** 检查文件名是否为空或者是否是Excel格式的文件 */if(filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath))){errorInfo= "文件名不是excel格式";return false;}/** 检查文件是否存在 */File file= new File(filePath);if(file == null || !file.exists()){errorInfo= "文件不存在";return false;}return true;}public List<List<String>> read(String filePath){List<List<String>> dataLst= new ArrayList<List<String>>();InputStream is= null;try{/** 验证文件是否合法 */if(!validateExcel(filePath)){System.out.println(errorInfo);return null;}/** 判断文件的类型,是2003还是2007 */boolean isExcel2003= true;if(WDWUtil.isExcel2007(filePath)){isExcel2003= false;}/** 调用本类提供的根据流读取的方法 */File file= new File(filePath);is= new FileInputStream(file);dataLst= read(is,isExcel2003);is.close();}catch (Exception ex){ex.printStackTrace();}finally{if(is != null){try{is.close();}catch (IOException e){is= null;e.printStackTrace();}}}/** 返回最后读取的结果 */return dataLst;}public List<List<String>> read(InputStream inputStream, boolean isExcel2003){List<List<String>> dataLst= null;try{/** 根据版本选择创建Workbook的方式 */Workbook wb= null;if(isExcel2003){wb= new HSSFWorkbook(inputStream);}else{wb= new XSSFWorkbook(inputStream);}dataLst= read(wb);}catch (IOException e){e.printStackTrace();}return dataLst;}private List<List<String>> read(Workbook wb){List<List<String>> dataLst= new ArrayList<List<String>>();/** 得到第一个shell */Sheet sheet= wb.getSheetAt(0);/** 得到Excel的行数 */this.totalRows= sheet.getPhysicalNumberOfRows();/** 得到Excel的列数 */if(this.totalRows >= 1 && sheet.getRow(0) != null){this.totalCells= sheet.getRow(0).getPhysicalNumberOfCells();}/** 循环Excel的行 */for(int r= 0; r < this.totalRows; r++){Row row= sheet.getRow(r);if(row == null){continue;}List<String> rowLst= new ArrayList<String>();/** 循环Excel的列 */for(int c= 0; c < this.getTotalCells(); c++){Cell cell= row.getCell(c);String cellValue= "";if(null != cell){// 以下是判断数据的类型switch(cell.getCellType()){case HSSFCell.CELL_TYPE_NUMERIC: // 数字cellValue= cell.getNumericCellValue() + "";break;case HSSFCell.CELL_TYPE_STRING: // 字符串cellValue= cell.getStringCellValue();break;case HSSFCell.CELL_TYPE_BOOLEAN: // BooleancellValue= cell.getBooleanCellValue() + "";break;case HSSFCell.CELL_TYPE_FORMULA: // 公式cellValue= cell.getCellFormula() + "";break;case HSSFCell.CELL_TYPE_BLANK: // 空值cellValue= "";break;case HSSFCell.CELL_TYPE_ERROR: // 故障cellValue= "非法字符";break;default:cellValue= "未知类型";break;}}rowLst.add(cellValue);}/** 保存第r行的第c列 */dataLst.add(rowLst);}return dataLst;}// 到处表格public void write(List<List<String>> source){// 第一步,创建一个webbook,对应一个Excel文件HSSFWorkbook wb= new HSSFWorkbook();// 第二步,在webbook中添加一个sheet,对应Excel文件中的sheetHSSFSheet sheet= wb.createSheet("省市");// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制shortHSSFRow row= sheet.createRow((int) 0);// 第四步,创建单元格,并设置值表头 设置表头居中HSSFCellStyle style= wb.createCellStyle();style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式HSSFCell cell= row.createCell((short) 0);cell.setCellValue("省");cell.setCellStyle(style);cell= row.createCell((short) 1);cell.setCellValue("市");cell.setCellStyle(style);cell= row.createCell((short) 2);cell.setCellValue("县");cell.setCellStyle(style);// 第五步,写入实体数据 实际应用中这些数据从数据库得到,List<List<String>> list= source;List<String> temp=new ArrayList<String>();for(int i= 0; i < list.size(); i++){row= sheet.createRow((int) i + 1);temp=list.get(i);// 第四步,创建单元格,并设置值for(int j=0;j<temp.size();j++){row.createCell((short) j).setCellValue(temp.get(j));}}// 第六步,将文件存到指定位置try{FileOutputStream fout= new FileOutputStream("E:/模版.xls");wb.write(fout);fout.close();}catch (Exception e){e.printStackTrace();}}public static void main(String[] args) throws Exception{importExcel poi= new importExcel();// List<List<String>> list = poi.read("d:/aaa.xls");List<List<String>> list= poi.read("E:/QQ文件/中国各省市邮政编码、电话区号大全.xls");if(list != null){for(int i= 0; i < list.size(); i++){System.out.print("第" + (i) + "行");List<String> cellList= list.get(i);for(int j= 0; j < cellList.size(); j++){// System.out.print(" 第" + (j + 1) + "列值:");System.out.print("    " + cellList.get(j));}System.out.println();}}}}class WDWUtil
{public static boolean isExcel2003(String filePath){return filePath.matches("^.+\\.(?i)(xls)$");}public static boolean isExcel2007(String filePath){return filePath.matches("^.+\\.(?i)(xlsx)$");}
}
package dealWithSource;import java.util.ArrayList;
import java.util.List;//处理表单。把表格调节成标准格式 (省,市,县)
public class createTable
{public static void main(String[] args){importExcel poi= new importExcel();// 省 市 县 List<List<String>> result= new ArrayList<List<String>>();try{List<List<String>> list= poi.read("E:/全国县级以上城市行政区划表.xls");if(list != null){//上一个省的名字,用于把省分隔开String previousProvince="";for(int i= 0; i < list.size(); i++){List<String> cellList= list.get(i);List<String> res= new ArrayList<String>();String province=cellList.get(0).trim();String city= dealWith(cellList.get(1).trim());String country=dealWith(cellList.get(2).trim());if(!previousProvince.equals(province)){previousProvince=province;//当遇到一个新的省的时候,那一行,就一个省字段,市,县为空res.add(province);res.add("");res.add("");result.add(res);res= new ArrayList<String>();}//省和市的照常添加res.add(province);res.add(city);if(country.equals("")||country.equals(city)){res.add("");// 县为空}else{res.add(country);}System.out.println(province+" "+city+" "+country);result.add(res);}}poi.write(result);}catch (Exception e){poi.write(result);e.printStackTrace();}}//给没加市的城市加上市,便于查找相应地区public static String dealWith(String result){result=result.trim();if(result==null||result.equals(""))return result;if(result.substring(result.length()-1).equals("镇")||result.substring(result.length()-1).equals("县")||result.substring(result.length()-1).equals("街道")||result.substring(result.length()-1).equals("区")||result.substring(result.length()-1).equals("旗")||(result.length()>4&&result.substring(result.length()-3).equals("自治州"))||(result.length()>2&&result.substring(result.length()-2).equals("街道")))return result;else{return result.trim()+"市";}}
}

然后这个文件用java application运行下,就可得到我要的初始数据模版了。

这里可以说明我为什么要先人为处理数据,而不是放到后面获取边界时一起处理。因为,减少bug的判断。万一后面出了很多bug要改,至少我能排除,我这里没有bug。也能确保后期万一我处理失败,这里每个数据元名字不会重复的再做处理。

然后我们就进入了工作阶段了跑数据,获取市中心以及边界。
什么是行政中心?不应该是简单的获取边界后取一个重心就当作城市中心的。而是应该以行政中心为准。大多数行政中心独有个特点。就是都是人民政府,如浙江省人民政府,这是省级的,到市级就有杭州市人民政府,县级有县级的人们政府。街道没有人民政府。自治州的是政府。开发区的只有管理委员会。当然,当你跑完数据后你也会发现一些特例,但是觉得不会多。到时候百度查找修改下就好了。
然后怎么获取数据呢?通过百度http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition 获取坐标
代码如下 先去百度地图获取个ak,然后下载个数据包

导入到程序里。(其实,这个不用服务器,直接用java application也可以运行出来的)

package service;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;public class Parser_Tool
{/*** post 获取 rest 资源* * @param url* @param name_value_pair* @return* @throws IOException*/public static String doPost(String url, List<NameValuePair> nameValuePair) throws IOException{String body= "{}";DefaultHttpClient httpclient= new DefaultHttpClient();try{HttpPost httpost= new HttpPost(url);httpost.setEntity(new UrlEncodedFormEntity(nameValuePair,StandardCharsets.UTF_8));HttpResponse response= httpclient.execute(httpost);HttpEntity entity= response.getEntity();body= EntityUtils.toString(entity);}finally{httpclient.getConnectionManager().shutdown();}return body;}/*** get 获取 rest 资源* * @param url* @return* @throws ClientProtocolException* @throws IOException*/public static String doGet(String url) throws ClientProtocolException, IOException{String body= "{}";DefaultHttpClient httpclient= new DefaultHttpClient();try{HttpGet httpget= new HttpGet(url);HttpResponse response= httpclient.execute(httpget);HttpEntity entity= response.getEntity();body= EntityUtils.toString(entity);}finally{httpclient.getConnectionManager().shutdown();}return body;}//把x,y坐标区分开public static String[] dealWith(String result){int x= result.indexOf("\"lng\":");int y= result.indexOf(",\"lat\":");int end= result.indexOf("},\"precise");if(x == -1){String[] answer= { "", "" };return answer;}String xs= result.substring(x + 6,y);String ys= result.substring(y + 7,end);String[] answer= { xs, ys };return answer;}}

这是个获取坐标的工具类。
然后我们就解决边界了。通过我是通过js调用百度地图api去获取的。
代码如下
这是jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>获取地区轮廓线</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3">
</script>
<style type="text/css">
body {font-size: 13px;margin: 10px
}#container {width: 800px;height: 500px;border: 1px solid gray
}
</style>
</head>
<body><div id="container"></div><br /> 输入省、直辖市或县名称:<script type="text/javascript">var map = new BMap.Map("container");map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5);map.addControl(new BMap.NavigationControl({type : BMAP_NAVIGATION_CONTROL_SMALL}));map.enableScrollWheelZoom();function getBoundary() { var bdary = new BMap.Boundary();var name = document.getElementById("districtName").value;bdary.get(name, function(rs) { //获取行政区域map.clearOverlays(); //清除地图覆盖物       var count = rs.boundaries.length; //行政区域的点有多少个for (var i = 0; i < count; i++) {var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight : 2,strokeColor : "#ff0000"}); //建立多边形覆盖物map.addOverlay(ply); //添加覆盖物map.setViewport(ply.getPath()); //调整视野         }var answer=document.getElementById("result");answer.value=rs.boundaries;});}setTimeout(getBoundary,1);setTimeout(a,5000);//  var i=0;function a(){//if(document.getElementById("result").value!="")document.getElementById("fom").submit();//else//{//      setTimeout(a,200);//  }}</script><form id="fom" action="excel" method="post"><input type="text" id="districtName" name="districtName" style="width: 80px" value="${result}"><input id="result" name="result" value=""></input><input onclick="getBoundary()" type="button" id="start" value="获取轮廓线"/><input type="submit" value="提交"/></form></body>
</html>

我这里是定时。5秒后自动提交数据。理由是,搜索需要时间。最晚5秒内肯定能好。不能设置一获取数据就传递到servlet里去,因为缺失存在一些找不到边界的。可能是百度地图里没有边界,或者省政府名字不正确,简写等导致的。这时候如果设置一获取数据就传递就会卡主。不动,除非手工按。所以我采用设置5秒自动提交。万一没有数据也不等了。直接提交。说明那个城市是有问题的。

package servlet;import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import service.WebExcel;@WebServlet("/excel")
public class servlce extends HttpServlet
{static WebExcel work;static boolean first=true;public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{String local= request.getParameter("result");//String now= new String(request.getParameter("districtName").getBytes("iso-8859-1"), "utf-8"); String next="";//下一个查找的城市if(first){first=false;work= new WebExcel();}next= work.doWork(local);if(next == "over")return; request.setAttribute("result",next);request.getRequestDispatcher("baiduMap.jsp").forward(request,response);}public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{doPost(request,response);}
}
package service;import java.util.ArrayList;
import java.util.List;import Dao.CountryDao;public class WebExcel
{int i = 0;static List<List<String>> list;static List<List<String>> result;String place;Excel poi;CountryDao dao;// 1.地理编码服务,即根据地址来查经度纬度String ak = "你百度获取的ak";String url1 = "http://api.map.baidu.com/geocoder/v2/?address=";String url2 = "&output=json&ak=" + ak;public WebExcel(){result = new ArrayList<List<String>>();dao = new CountryDao();poi = new Excel();list = poi.readExcel();}// 为每个城市添加边境范围坐标public String doWork(String border){try{if (list != null && i < list.size()){// 每一列加范围坐标if (i != 0){List<String> temp = new ArrayList<String>();String province = list.get(i).get(0);String city = list.get(i).get(1);String country = list.get(i).get(2);temp.add(province);// 放入省市temp.add(city);// 放入市区temp.add(country);// 放入县place = "";// 获取中心点坐标if (city.equals("")){place = province;// 放入省}else if (country.equals("")){place = city;// 放入市}else{if (city.substring(city.length() - 1).equals("市"))place = city.substring(0, city.length() - 1) + country;// 放入县elseplace = city + country;}if (place.length() >= 3){String end = place.substring(place.length() - 3);if (end.equals("自治州")){place += "政府";}if (end.equals("开发区")){place += "管理委员会";}else{place += "人民政府";}}//获取中心点的x,yString[] answer = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));temp.add(answer[0]);temp.add(answer[1]);System.out.println(place+": x:"+answer[0]+" y:"+answer[1]);// x,y区分处理String[] arr = border.split(",|;");String x = "";String y = "";for(int i = 0; i < arr.length; i++){if (i % 2 == 0){if (i != arr.length - 2)x += arr[i] + ",";else{x += arr[i];}}else{if (i != arr.length - 1)y += arr[i] + ",";else{y += arr[i];}}}temp.add(x);// 放入边界范围temp.add(y);result.add(temp);// dao.addExcel(temp);}else{// 默认导入的是同一个数据源result = dao.getDate();i=result.size();}System.out.println("边界范围" + ":"+border);i++;if (i >= list.size()){dao.addAllExcel(result);// dao.fillBorder(result);return "over";}//返回下一个省if(list.get(i).get(1).equals(""))return list.get(i).get(0);//返回下一个市if(list.get(i).get(2).equals(""))return list.get(i).get(0)+list.get(i).get(1);else{if (list.get(i).get(1).substring(list.get(i).get(1).length() - 1).equals("市"))place = list.get(i).get(0)+list.get(i).get(1).substring(0, list.get(i).get(1).length() - 1) + list.get(i).get(2);// 放入县elseplace = list.get(i).get(0)+list.get(i).get(1) + list.get(i).get(2);return place;}}return "over";}catch(Exception e){e.printStackTrace();dao.addAllExcel(result);return "over";}}
}

我当时是分开做实验的。获取地址和边界。所以获取边界的时候我是采用另一种方式读取excelde 。用的是jxl
导入个这个包就好了

package service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;public class Excel
{File file = new File("E:模版.xls");File write = new File("E:");List<List<String>> library = new ArrayList<List<String>>();int i = 0, j = 0;public Excel(){}// 去读Excel的方法readExcel,该方法的入口参数为一个File对象public List<List<String>> readExcel(){try{// 创建输入流,读取ExcelInputStream is = new FileInputStream(file.getAbsolutePath());// jxl提供的Workbook类Workbook wb = Workbook.getWorkbook(is);// Excel的页签数量int sheet_size = wb.getNumberOfSheets();for(int index = 0; index < sheet_size; index++){// 每个页签创建一个Sheet对象Sheet sheet = wb.getSheet(index);// sheet.getRows()返回该页的总行数for(int i = 0; i < sheet.getRows(); i++){// sheet.getColumns()返回该页的总列数List<String> temp = new ArrayList<String>();for(int j = 0; j < sheet.getColumns(); j++){String cellinfo = sheet.getCell(j, i).getContents();temp.add(cellinfo);//          System.out.println(cellinfo);}library.add(temp);}}return library;}catch(FileNotFoundException e){e.printStackTrace();}catch(BiffException e){e.printStackTrace();}catch(IOException e){e.printStackTrace();}return null;}// 去读Excel的方法readExcel,该方法的入口参数为一个File对象public void writeExcel(List<List<String>> out){try{// 打开文件WritableWorkbook book = Workbook.createWorkbook(new File("final.xls"));// 生成名为“sheet1”的工作表,参数0表示这是第一页WritableSheet sheet = book.createSheet("sheet1", 0);// 在Label对象的构造子中指名单元格位置是第一列第一行(0,0),单元格内容为stringfor(int i = 0; i < out.size(); i++)for(int j = 0; j < out.get(i).size(); j++){Label label = new Label(j,i, out.get(i).get(j));// 将定义好的单元格添加到工作表中sheet.addCell(label);}// 写入数据并关闭文件book.write();book.close();}catch(Exception e){System.out.println(e);}}
}

我把结果直接写到数据库的

package Dao;import java.sql.Connection;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;public class BaseDao
{DataSource dataSource;//构造方法中返回数据源对象public BaseDao(){try{Context context=new InitialContext();dataSource=(DataSource)context.lookup("java:comp/env/jdbc/yanfan");}catch(NamingException ne){ne.printStackTrace();}}//返回一个连接对象public Connection getConnection()throws Exception{return dataSource.getConnection();}
}
package Dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;import com.mysql.jdbc.Statement;public class CountryDao extends BaseDao
{Connection conn;PreparedStatement pstmt;Statement stmt;ResultSet rst;// 插入国家信息记录(全部)public boolean addAllExcel(List<List<String>> list){String sql = "insert into china (province,city,country,xcenter,ycenter,xborders,yborders) values(?,?,?,?,?,?,?)";try{conn = dataSource.getConnection();for(int i = 0; i < list.size(); i++){pstmt = conn.prepareStatement(sql);pstmt.setString(1, list.get(i).get(0));pstmt.setString(2, list.get(i).get(1));pstmt.setString(3, list.get(i).get(2));pstmt.setString(4, list.get(i).get(3));pstmt.setString(5, list.get(i).get(4));pstmt.setString(6, list.get(i).get(5));pstmt.setString(7, list.get(i).get(6));pstmt.executeUpdate();}System.out.println("完成");return true;}catch(SQLException se){se.printStackTrace();return false;}}// 添加单个数据元public boolean addExcel(List<String> list){String sql = "insert into china (province,city,country,xcenter,ycenter,xborders,yborders) values(?,?,?,?,?,?,?)";try{conn = dataSource.getConnection();pstmt = conn.prepareStatement(sql);for(int i = 0; i < list.size(); i++){pstmt.setString(i + 1, list.get(i));}pstmt.executeUpdate();System.out.println("完成");return true;}catch(SQLException se){se.printStackTrace();return false;}}// 先检查数据库里已经存在了多少个数据,减少重复输入public List<List<String>> getDate(){List<List<String>> result = new ArrayList<List<String>>();String sql = "SELECT * FROM work.china";try{conn = dataSource.getConnection();pstmt = conn.prepareStatement(sql);rst = pstmt.executeQuery();// 获取元数据ResultSetMetaData rsmd = rst.getMetaData();while(rst.next()){List<String> temp = new ArrayList<String>();// 根据结果表得出的for(int i = 0; i < rsmd.getColumnCount(); i++){String conlumnLabel = rsmd.getColumnLabel(i + 1);Object comlumnValue = rst.getObject(conlumnLabel);temp.add("" + comlumnValue);}result.add(temp);}return result;}catch(SQLException e){// TODO Auto-generated catch blocke.printStackTrace();return null;}}// 获取缺失边界点的数据public List<List<String>> getBordersDate(){List<List<String>> result = new ArrayList<List<String>>();String sql = "SELECT * FROM work.china where xborders=',' and yborders=''";try{conn = dataSource.getConnection();pstmt = conn.prepareStatement(sql);rst = pstmt.executeQuery();// 获取元数据ResultSetMetaData rsmd = rst.getMetaData();while(rst.next()){List<String> temp = new ArrayList<String>();// 根据结果表得出的for(int i = 0; i < rsmd.getColumnCount(); i++){String conlumnLabel = rsmd.getColumnLabel(i +1);Object comlumnValue = rst.getObject(conlumnLabel);temp.add("" + comlumnValue);}result.add(temp);}return result;}catch(SQLException e){// TODO Auto-generated catch blocke.printStackTrace();return null;}}// 获取缺少中心点的数据public List<List<String>> getCenterDate(){List<List<String>> result = new ArrayList<List<String>>();String sql = "SELECT * FROM work.china where xcenter='' and ycenter=''";try{conn = dataSource.getConnection();pstmt = conn.prepareStatement(sql);rst = pstmt.executeQuery();// 获取元数据ResultSetMetaData rsmd = rst.getMetaData();while(rst.next()){List<String> temp = new ArrayList<String>();// 根据结果表得出的for(int i = 0; i < rsmd.getColumnCount(); i++){String conlumnLabel = rsmd.getColumnLabel(i + 1);Object comlumnValue = rst.getObject(conlumnLabel);temp.add("" + comlumnValue);}result.add(temp);}return result;}catch(SQLException e){// TODO Auto-generated catch blocke.printStackTrace();return null;}}// 检查填充边界的数据public boolean fillBorder(List<List<String>> list){String sql = "update china set country = ?,xborders = ? ,yborders=? where province = ? and city = ? and country = ?";try{conn = dataSource.getConnection();pstmt = conn.prepareStatement(sql);System.out.println("数量"+list.size());for(int i=0;i<list.size();i++){pstmt.setString(1, list.get(i).get(7));pstmt.setString(2, list.get(i).get(5));pstmt.setString(3, list.get(i).get(6));pstmt.setString(4, list.get(i).get(0));pstmt.setString(5, list.get(i).get(1));pstmt.setString(6, list.get(i).get(2));System.out.println("加载"+i);pstmt.executeUpdate();System.out.println("完成"+i);}System.out.println("完成");return true;}catch(SQLException e){// TODO Auto-generated catch blocke.printStackTrace();return false;}}// 填充中心public boolean fillCenter(List<List<String>> list){String sql = "update china set country = ? ,xcenter = ? ,ycenter=? where province = ? and city = ? and country = ?";try{conn = dataSource.getConnection();pstmt = conn.prepareStatement(sql);for(int i = 0; i < list.size(); i++){pstmt.setString(1, list.get(i).get(2));pstmt.setString(2, list.get(i).get(3));pstmt.setString(3, list.get(i).get(4));pstmt.setString(4, list.get(i).get(0));pstmt.setString(5, list.get(i).get(1));pstmt.setString(6, list.get(i).get(2));pstmt.executeUpdate();}return true;}catch(SQLException e){// TODO Auto-generated catch blocke.printStackTrace();return false;}}
}

记得配置个context.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true"><Resource name="jdbc/yanfan" type="javax.sql.DataSource"maxActive="40" maxIdle="29" username="root" maxWait="5000"driverClassName="com.mysql.jdbc.Driver" password="123456789"url="jdbc:mysql://localhost:3306/work" />
</Context>

有了以上代码后就可以开始跑数据了。修改下数据库地方就可以了

跑下来可能存在一些数据不正确,比如名字不对,还有可能一些城市已经合并了。因为原数据是近两年的。但是这两年也有些城市发生了变动,所以我只能一个个百度,找到有问题的城市查明原因,去对应修改。修改数据的代码如下

package service;import java.util.ArrayList;
import java.util.List;import Dao.CountryDao;//用于填空的坐标
public class FillBorder
{List<List<String>> list;List<List<String>> result = new ArrayList<List<String>>();CountryDao dao = new CountryDao();String ak = "你的百度ak";String url1 = "http://api.map.baidu.com/geocoder/v2/?address=";String url2 = "&output=json&ak=" + ak;String place = "";int i = 0;// 行static boolean end;public FillBorder(){list = dao.getBordersDate();System.out.println("边界缺损数量:" + list.size());}public String doWork(String border){try{if(end)return "over";String[] arr = border.split(",|;");String x = "", y = "";List<String> temp = new ArrayList<String>();if (i >= list.size()){dao.fillBorder(result);end=true;return "over";}//加入省,市for(int j = 0; j < 2; j++){temp.add(list.get(i).get(j));}//加入县String country = list.get(i).get(2);if ((country.length() > 3 && country.substring(country.length() - 3).equals("街道市"))||(country.length() > 2 && country.substring(country.length() - 2).equals("旗市"))){country = country.substring(0, country.length() - 1);// 去掉街道名字里的市}if ((country.length() > 3 && country.substring(country.length() - 3).equals("县图市"))){country = country.substring(0, country.length() - 2);// 去掉街道名字里的图市}temp.add(list.get(i).get(2));temp.add(list.get(i).get(3));temp.add(list.get(i).get(4));if ((country.length()>0&&country.substring(country.length() - 1).equals("镇"))||(country.length()>2&&country.substring(country.length()-2).equals("街道"))){String city = list.get(i).get(1);if (city.substring(city.length() - 1).equals("市")){city = city.substring(0, city.length() - 1);}place += city + country;String[] town = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));temp.add(town[0]);temp.add(town[1]);temp.add(country);System.out.println(temp.get(7) + " 边界:" + town[0]+" , "+town[1]);}else{for(int i = 0; i < arr.length; i++){if (i % 2 == 0){x += arr[i];if (i != arr.length - 2){x += ",";}}else{y += arr[i];if (i != arr.length - 1){y += ",";}}}temp.add(x);temp.add(y);temp.add(country);System.out.println(temp.get(2) + " 边界:" + border);}result.add(temp);++i;if (i >= list.size()){dao.fillBorder(result);return "over";}country = list.get(i).get(2);if ((country.length() > 3 && country.substring(country.length() - 3).equals("街道市"))||(country.length() > 2 && country.substring(country.length() - 2).equals("旗市"))){country = country.substring(0, country.length() - 1);// 去掉街道名字里的市}if ((country.length() > 3 && country.substring(country.length() - 3).equals("县图市"))){country = country.substring(0, country.length() - 2);// 去掉街道名字里的图市}return list.get(i).get(0)+list.get(i).get(1)+country;}catch(Exception e){e.printStackTrace();dao.fillBorder(result);return "over";}}public String first(){String first = list.get(i).get(0)+list.get(i).get(1)+list.get(i).get(2);return first;}
}
package service;import java.util.List;import Dao.CountryDao;//用于填空的坐标
public class FillCenter
{List<List<String>> list;CountryDao dao = new CountryDao();// 1.地理编码服务,即根据地址来查经度纬度String ak = "你的百度ak";String url1 = "http://api.map.baidu.com/geocoder/v2/?address=";String url2 = "&output=json&ak=" + ak;String place;public FillCenter(){list = dao.getCenterDate();System.out.println("一共有及格没找到中心点" + list.size());}public boolean doWork(){try{for(int i = 0; i < list.size(); i++){if (list.get(i).get(2).equals("")){place = list.get(i).get(1);if (place.equals("芒市"))place += "人民政府";if (place.equals("三沙市"))place += "政府";String[] center = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));list.get(i).set(3, center[0]);list.get(i).set(4, center[1]);System.out.println(place + "x:" + center[0] + " y:" + center[1]);continue;}place = list.get(i).get(2);if (place.substring(place.length() - 2).equals("旗市")){place.substring(0, place.length() - 1);// 修改名字,去掉市list.get(i).set(2, place);}if (place.equals("镇原县"))place += "人民政府政务大厅";else if (place.equals("镇平县") || place.equals("樊城区") || place.equals("襄城区") || place.equals("红寺堡区")|| place.equals("茂县"))place += "政府";else if (place.equals("郧县"))place += "政协";elseplace += "人民政府";String[] center = Parser_Tool.dealWith(Parser_Tool.doGet(url1 + place + url2));list.get(i).set(3, center[0]);list.get(i).set(4, center[1]);System.out.println(place + "x:" + center[0] + " y:" + center[1]);}return dao.fillCenter(list);}catch(Exception e){e.printStackTrace();dao.fillCenter(list);return false;}}}
package servlet;
import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import service.FillBorder;
import service.FillCenter;
@WebServlet("/fillBack")
public class fillBack extends HttpServlet
{boolean first=true;String city=null;FillBorder fill=new FillBorder();public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{String border=request.getParameter("result");System.out.println(border);if(first){//顺手填了中心的坐标系FillCenter fillCenter=new FillCenter();fillCenter.doWork();first=false;city=fill.first();}else{city=fill.doWork(border);}if(city == "over")return; request.setAttribute("result",city);request.getRequestDispatcher("fillBorder.jsp").forward(request,response);}public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{doPost(request,response);}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>获取地区轮廓线</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3">
</script>
<style type="text/css">
body {font-size: 13px;margin: 10px }#container {width: 800px;height: 500px;border: 1px solid gray }
</style>
</head>
<body><div id="container"></div><br /> 输入省、直辖市或县名称:<script type="text/javascript">var map = new BMap.Map("container");map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5);map.addControl(new BMap.NavigationControl({type : BMAP_NAVIGATION_CONTROL_SMALL}));map.enableScrollWheelZoom();function getBoundary() { var bdary = new BMap.Boundary();var name = document.getElementById("districtName").value;bdary.get(name, function(rs) { //获取行政区域map.clearOverlays(); //清除地图覆盖物       var count = rs.boundaries.length; //行政区域的点有多少个for (var i = 0; i < count; i++) {var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight : 2,strokeColor : "#ff0000"}); //建立多边形覆盖物map.addOverlay(ply); //添加覆盖物map.setViewport(ply.getPath()); //调整视野         }var answer=document.getElementById("result");answer.value=rs.boundaries;});}setTimeout(getBoundary,1);setTimeout(a,5000);function a(){document.getElementById("fom").submit();}</script><form id="fom" action="fillBack" method="post"><input type="text" id="districtName" name="districtName" style="width: 80px" value="${result}"><input id="result" name="result" value=""></input><input onclick="getBoundary()" type="button" id="start" value="获取轮廓线"/><input type="submit" value="提交"/></form></body>
</html>

经过这些数据处理就可以了.顺序是先用省,市县去找。然后再用市县去找,最后再用县去找。跑三次,就可以确定这些数据最全了。剩下的得人工修改。因为省市县名字不对。或者城市已经没了,或者简写找不到等导致的。
带吗到数据库里修改(Sql代码)

//删除没有的数据(城市已经被合并了)
delete from china where province=''//修改数据(因为没有主键,直接修改会报错Error: 1175 SQLSTATE: HY000 (ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE))
//这是先运行下     SET SQL_SAFE_UPDATES = 0;  修改下更新模式就好
update china set xborders=',',yborders='' where province='浙江省'//查询语句
SELECT * FROM work.china;//如果数据里面有重复的,可以采用再建立的temp表。和china表一模一样的。
//然后运行sql语句
insert into temp select distanct * from china;
truncate table china;
insert into china select distanct * from temp;
//如果不需要temp了可以人工删除


然后就好了。
一下是我的代码。得自己创建下数据库,按照自己的数据库修改下代码context等部分。
http://download.csdn.net/download/qq_33359282/9896354

全国各省市县级边界范围及其中心城区查询(调用百度地图)相关推荐

  1. 计算机专业最低院校门槛,2021年全国各省高考高校录取最低位次排名查询系统...

    高考录取位次 高考录取位次指考生的高考总分在本省某科类全体考生中的排名顺序,考生的位次如果高于一所学校历年录取最低分位次,则意味着报考这所学校被投档录取的可能性很大. 2021年全国各省高考高校录取最 ...

  2. 调用百度地图接口获取城市住宅小区边界信息 (米制转经纬度)

    一.背景需求: 在百度地图上查询一个住宅小区, 界面会显示一个小区的边界阴影.大小区.新小区有:一些老小区也没有.我们老大看到了让我也整一个出来,大概就是输入小区名称,地图上展示出这个小区的边界轮廓. ...

  3. 调用百度地图接口获取城市住宅小区边界信息

    一. 背景描述 在百度地图上查询一个住宅小区, 界面会显示一个小区的边界阴影.大小区.新小区有:一些老小区也没有.这些边界坐标有时我们也想拿到,用于在做各种地图相关的计算和展示. 二. 获取住宅小区边 ...

  4. python调用百度地图API批量查询全国高速收费站点经纬度

    写在前面 大家好,我是饭都吃不起的南南 昨天帮朋友爬了全国的高速站点收费站这里下载 [http://www.bestunion.cn/gaosu/p_4/sfzlist.html] 由于该网站并没有西 ...

  5. python爬虫学习之爬取全国各省市县级城市邮政编码

    实例需求:运用python语言在ip查询 查ip 网站ip查询 同ip网站查询 iP反查域名 iP查域名 同ip域名网站爬取全国各个省市县级城市的邮政编码,并且保存在excel文件中 实例环境:pyt ...

  6. python输入城市找省份_python爬虫学习之爬取全国各省市县级城市邮政编码

    importrequestsimportxlwt#返回一个字典,键是各个省份的名字,值是对应省份的网址url defgetProvinceCode(url): response=requests.ge ...

  7. masonry的约束应该写在哪里_规划奇思|“中心城区”到底在哪里?和城镇开发边界是什么关系?...

    随着9月发行的<市级国土空间总体规划编制指南(试行)>和<湖南省县级国土空间总体规划编制指南(试行)>,基本明确了市级和县级国土空间规划的两个层次,即全域和中心城区,两个不同层 ...

  8. Python采集全国各地百度地图上店铺POI数据(母婴、美食等)

    Python采集全国各地百度地图上店铺POI数据 1. 注册百度地图开放平台账号 先注册百度地图开发平台账号,创建应用,获得AK 2. 通过Python批量检索不同城市店铺POI数据 2.1 大致思路 ...

  9. 奥维查看行政边界_【百度地图API】如何获取行政区域的边界? (转载)

    摘要:以前教过大家如何自行获取行政区域,或者自定义获取一个区域的边界值.今天来教大家直接调用百度地图API1.3(目前最新版本)来获取行政区域的边界值. ----------------------- ...

最新文章

  1. 【C++】Effective STL:50条有效使用STL的经验
  2. SQL Server基础之存储过程
  3. Asp.net生成Excel文件并下载(解决使用迅雷下载页面而不是文件的问题)
  4. 一种新颖的流程控制方式
  5. Java程序员的10个XML面试问答
  6. /bin/false /sbin/nologin
  7. 【ElasticSearch】Es 源码之 MonitorService 源码解读
  8. matlab没有曲线,有个程序,运行后只有坐标没有曲线,是怎么回事呢 望大神们解答...
  9. 每日一篇_启动又报错了The POM for com.xxxx:qgg-core:jar:0.0.1-SNAPSHOT is missing
  10. 海胆状金纳米颗粒,粒径:150-200nm|银包金纳米颗粒 粒径:5-200nm|碳包金纳米颗粒 粒径:可定制
  11. 博客搬家系列(六)-爬取今日头条文章
  12. 作为一个程序员: 这么奇葩搞笑的代码注释你见过吗?
  13. 用jacob为word表格设置边框线
  14. 基于深度卷积神经网络的人脸识别考勤系统-VGG-PYTHON-QT(1)
  15. 收藏!17 张程序员专属壁纸(使用频率很高)
  16. 十字军东征一些君主AI的对话
  17. uboot.lds链接脚本分析
  18. mysql utl_file_pl/sql应用之利用utl_file写文件
  19. ThinkPad安装Mac
  20. 计算机网络考试重点复习(本科)

热门文章

  1. 瑞熙贝通大型仪器共享预约平台建设方案
  2. [Unity 架构] 更好的 Unity 游戏架构
  3. spring学习笔记(1)——B站动力节点
  4. pc端rem适配_聊聊PC端页面适配
  5. 个人网页(HTML+css)
  6. [激光原理与应用-51]:《激光焊接质量实时监测系统研究》-2-激光焊接及其物理现象
  7. [网络工程师]-网络规划与设计-物理网络设计
  8. 取其精华,去其糟粕——前后端交互的计算器——servlet、html、JavaScript、Tomcat
  9. 2、SPSS的基本知识
  10. 关于e^x的部分公式和约算方法