獲取OpenStreetMap最新矢量行政區(qū)劃圖(2020中國行政區(qū)劃shp)

之前項目上發(fā)布地圖服務時候伺帘,被客戶嫌棄我們使用的地圖shp數據版本太老了(2014版)
含淚啜泣

于是乎伪嫁,領導拍板了,更新帝洪!必須更新似舵!

找遍各大網絡數據,最新版的中國行政區(qū)劃圖(省市縣級)葱峡,最新版更新到2015年砚哗,嗯,還是不知道是否真的2015砰奕。然后蛛芥,爬遍了城墻內外,萬能寶一份2017的數據100+军援,地理空間數據云的仅淑,一份縣級中國區(qū)劃2014版,報價十幾萬……
窮就一個字

鑒于真實的2020數據胸哥,大概率小貧民是不可獲得的(涉密),只能從開源數據上想想辦法了空厌。

鑒于之前爬遍全網的經歷庐船,目光直接鎖定OpenStreetMap的數據,開源蝇庭、免費醉鳖、并且經過驗證,矢量邊界比手中現(xiàn)有的行政區(qū)劃更加精細哮内。缺點則是涉及到領土有爭議的部分領域盗棵,OSM是站在對立面的,童鞋們慎重氨狈ⅰ纹因!

來吧,話不多說,上干貨!

1. 技術路線介紹

根據之前掌握的信息腮郊,OSM官方是提供矢量圖形下載的。大概是我使用的導出方式不對惊畏,一直沒能下下來。

已選中區(qū)域下載

經過多方找了GeoJSON中的OpenStreetMap管理邊界
以及提取OSM行政邊界的方法, 確認OSM當前的行政邊界的下載的方式密任。整體路線大概是

1. 獲取所有行政區(qū)劃的relation code颜启,
2. 通過CURL命令下載。(大概率需要科學上網)
備案方法2:通過[http://polygons.openstreetmap.fr/?id=RELATIONID](http://polygons.openstreetmap.fr/?id=)
獲取到圖形自動入庫浪讳。(此方法建議無法科學上網的童鞋們使用缰盏。)

2. 獲取關系編碼

通過觀察網頁中的相關信息,咱們可以快速的看到,每一個區(qū)域的編號口猜,以及與它接壤的外圍編號负溪,以及它的子一級編號


OSM區(qū)域上下關系code

鑒于此,中國34個省市的關系網盡在掌握济炎。
數據獲取邏輯如下:

  1. 獲取中國34個省市縣的關系網川抡;
  2. 向下查找每個省市對應的市級關系編碼;
  3. 根據市級關系編碼冻辩,再向下查找縣級編碼猖腕。
    基于此拆祈,便可獲取全中國34個省市縣區(qū)最新的shp矢量行政區(qū)劃了恨闪。

一個簡單的爬蟲小程序便應運而生。

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();
                //獲取節(jié)點數據
                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<>();
                //循環(huán)讀取市級節(jié)點
                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);
            }
            //根據市級節(jié)點的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

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末梗摇,一起剝皮案震驚了整個濱河市拓哟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伶授,老刑警劉巖断序,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糜烹,居然都是意外死亡违诗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門景图,熙熙樓的掌柜王于貴愁眉苦臉地迎上來较雕,“玉大人,你說我怎么就攤上這事×两” “怎么了扣典?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慎玖。 經常有香客問我贮尖,道長,這世上最難降的妖魔是什么趁怔? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任湿硝,我火速辦了婚禮,結果婚禮上润努,老公的妹妹穿的比我還像新娘关斜。我一直安慰自己,他們只是感情好铺浇,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布痢畜。 她就那樣靜靜地躺著,像睡著了一般鳍侣。 火紅的嫁衣襯著肌膚如雪丁稀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天倚聚,我揣著相機與錄音线衫,去河邊找鬼。 笑死惑折,一個胖子當著我的面吹牛授账,可吹牛的內容都是我干的。 我是一名探鬼主播唬复,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼矗积,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敞咧?” 一聲冷哼從身側響起棘捣,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎休建,沒想到半個月后乍恐,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡测砂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年茵烈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砌些。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡呜投,死狀恐怖加匈,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情仑荐,我是刑警寧澤雕拼,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站粘招,受9級特大地震影響啥寇,放射性物質發(fā)生泄漏。R本人自食惡果不足惜洒扎,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一辑甜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袍冷,春花似錦磷醋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镊掖。三九已至乃戈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亩进,已是汗流浹背症虑。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留归薛,地道東北人谍憔。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像主籍,于是被迫代替她去往敵國和親习贫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348