于是乎,领导拍板了,更新!必须更新!
找遍各大网络数据,最新版的中国行政区划图(省市县级),最新版更新到2015年,嗯,还是不知道是否真的2015。然后,爬遍了城墙内外,万能宝一份2017的数据100+,地理空间数据云的,一份县级中国区划2014版,报价十几万……鉴于真实的2020数据,大概率小贫民是不可获得的(涉密),只能从开源数据上想想办法了。
鉴于之前爬遍全网的经历,目光直接锁定OpenStreetMap的数据,开源、免费、并且经过验证,矢量边界比手中现有的行政区划更加精细。缺点则是涉及到领土有争议的部分领域,OSM是站在对立面的,童鞋们慎重啊!
来吧,话不多说,上干货!
1. 技术路线介绍
根据之前掌握的信息,OSM官方是提供矢量图形下载的。大概是我使用的导出方式不对,一直没能下下来。
经过多方找了GeoJSON中的OpenStreetMap管理边界
以及提取OSM行政边界的方法, 确认OSM当前的行政边界的下载的方式。整体路线大概是
1. 获取所有行政区划的relation code,
2. 通过CURL命令下载。(大概率需要科学上网)
备案方法2:通过[http://polygons.openstreetmap.fr/?id=RELATIONID](http://polygons.openstreetmap.fr/?id=)
获取到图形自动入库。(此方法建议无法科学上网的童鞋们使用。)
2. 获取关系编码
通过观察网页中的相关信息,咱们可以快速的看到,每一个区域的编号,以及与它接壤的外围编号,以及它的子一级编号
鉴于此,中国34个省市的关系网尽在掌握。
数据获取逻辑如下:
- 获取中国34个省市县的关系网;
- 向下查找每个省市对应的市级关系编码;
- 根据市级关系编码,再向下查找县级编码。
基于此,便可获取全中国34个省市县区最新的shp矢量行政区划了。
一个简单的爬虫小程序便应运而生。
package com.openstreetmap.reptile;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Node;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author
* @Date: 2020/1/16 13:55
* @Description: 用于处理爬虫逻辑
**/
@Slf4j
public class FileReptileCore {
public static void main(String[] args) {
try {
//34个省市县的编码
String code ="913011;553303;153314;911844;286937;2128285;912998;199073;407492;913106;913073;913012;913109;198590;912942;" +
"153269;913100;913006;913105;913068;913094;553302;153292;153310;286342;161349;" +
"913101;912940;912999;913067;913069;913110;1867188";
String[] codeArr = code.split(";");
Map<String,List<String>> cityLevelCode = new HashMap<>();
//基础的访问网址
String baseUrl = "https://www.openstreetmap.org/relation/";
for (int i = 0; i < codeArr.length; i++) {
//输出当前正在爬取的省份编码
log.info("===========开始输出:" + codeArr[i]);
String url = baseUrl + codeArr[i];
org.jsoup.nodes.Document doc = Jsoup.connect(url).ignoreContentType(true).timeout(30000).get();
//获取节点数据
List<Node> relationNodeList = doc.body().childNodes().get(3).childNodes().get(1).childNodes().get(9).childNodes().get(3).childNodes()
.get(17).childNodes();
int size = relationNodeList.size();
List<String> cityCode = new ArrayList<>();
//循环读取市级节点
for (int j = 0; j < size; j++) {
Node node = relationNodeList.get(j);
if(node.toString().equals(" ")){
continue;
}
String value = node.childNodes().get(1).attributes().get("href");
if(value.contains("relation")){
String relationCode = value.split("/")[2];
cityCode.add(relationCode);
System.out.println(relationCode);
}
}
cityLevelCode.put(codeArr[i],cityCode);
}
//根据市级节点的code,获得县级的code
for (Map.Entry province :cityLevelCode.entrySet()) {
List<String> cityCodeArr = (List<String>)province.getValue();
int cityCodeArrsize = cityCodeArr.size();
for (int a = 0; a < cityCodeArrsize; a++) {
log.info("===========开始输出:" + cityCodeArr.get(a));
String url = baseUrl + cityCodeArr.get(a);
org.jsoup.nodes.Document doc = Jsoup.connect(url).ignoreContentType(true).timeout(30000).get();
List<Node> relationNodeList = doc.body().childNodes().get(3).childNodes().get(1).childNodes().get(9).childNodes().get(3).childNodes()
.get(17).childNodes();
int size = relationNodeList.size();
for (int j = 0; j < size; j++) {
Node node = relationNodeList.get(j);
if(node.toString().equals(" ")){
continue;
}
String value = node.childNodes().get(1).attributes().get("href");
if(value.contains("relation")){
String relationCode = value.split("/")[2];
System.out.println(relationCode);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
基于此,所有省市县的编码获取完毕。
3. 根据编码下载shp
根据这位大大的文章OSM行政边界的方法, 使用CURL命令即可
curl -f -o file.zip --url
"https://wambachers-osm.website/boundaries/exportBoundaries?cliVersion=1.0&cliKey=52d97a3b-3fc1-44cd-bd9a-e8c1c9468bab&exportFormat=shp&exportLayout=levels&exportAreas=land&union=false&selected=3287346"
其中:
curl -f -o 代表下载操作;
file.zip: 表示下载的文件名;
--url: 代表将此url下面的文件下载下来
整个链接:https://wambachers-osm.website/boundaries/exportBoundaries?cliVersion=1.0&cliKey=52d97a3b-3fc1-44cd-bd9a-e8c1c9468bab&exportFormat=shp&exportLayout=levels&exportAreas=land&union=false&selected=3287346中,需要修改的部分便是327346,这个就是上文获取的code。多文件下载时,仅需将多个code使用 , 隔开即可
比如:
curl -f -o file.zip --url
"https://wambachers-osm.website/boundaries/exportBoundaries?cliVersion=1.0&cliKey=52d97a3b-3fc1-44cd-bd9a-e8c1c9468bab&exportFormat=shp&exportLayout=levels&exportAreas=land&union=false&selected=3287346,2963917
等等……
备注
至于备选方法,只要拿到了关系代码,也是一个简单查询命令便可转存入库。在此便不赘述。
关于上文介绍的数据,如有需要,有偿私信哈~Q或者邮箱是(344326924@qq.com)