[python] 下載天地圖切片地圖

下載xyz地圖

資源

  • 下列爲常用xyz路由地址
  • 爲了避免圖片中出現文字標註(道路名稱,建築物名稱等)本文選擇天地圖tian-vec 作爲獲取資源對象
    var mapUrl = {
        /****
         * 高德地圖
         * lang可以通過zh_cn設置中文,en設置英文,size基本無作用,scl設置標註還是底圖,scl=1代表註記,
         * scl=2代表底圖(矢量或者影像),style設置影像和路網,style=6爲影像圖,
         * vec——街道底圖
         * img——影像底圖
         * roadLabel---路網+標註
         */
        "aMap-img": "http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
        "aMap-vec": "http://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
        "aMap-roadLabel": "http://webst0{1-4}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}",
        /***
         * 天地圖 要key的
         * vec——街道底圖
         * img——影像底圖
         * ter——地形底圖
         * cva——中文註記
         * cta/cia——道路+中文註記 ---roadLabel
         */
        "tian-img": "http://t{0-7}.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=a4ee5c551598a1889adfabff55a5fc27",
        "tian-roadLabel": "http://t{0-7}.tianditu.gov.cn/DataServer?T=cta_w&x={x}&y={y}&l={z}&tk=a4ee5c551598a1889adfabff55a5fc27",
        "tian-label": "http://t{0-7}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=a4ee5c551598a1889adfabff55a5fc27",
        "tian-vec": "http://t{0-7}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=a4ee5c551598a1889adfabff55a5fc27",
        "tian-ter": "http://t{0-7}.tianditu.gov.cn/DataServer?T=ter_w&x={x}&y={y}&l={z}&tk=a4ee5c551598a1889adfabff55a5fc27",
        /***
         *geoq地圖
         * http://cache1.arcgisonline.cn
         * http://map.geoq.cn
         * vec:標準彩色地圖
         * gray、blue、warm
         * line 中國輪廓圖
         * china 中國輪廓圖+標註
         * Hydro 水系
         * green 植被
         */
        "geoq-vec": "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}",
        "geoq-gray": "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetGray/MapServer/tile/{z}/{y}/{x}",
        "geoq-blue": "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
        "geoq-warm": "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer/tile/{z}/{y}/{x}",
        "geoq-line": "http://cache1.arcgisonline.cn/arcgis/rest/services/SimpleFeature/ChinaBoundaryLine/MapServer/tile/{z}/{y}/{x}",//不穩定
        "geoq-china": "http://thematic.geoq.cn/arcgis/rest/services/ThematicMaps/administrative_division_boundaryandlabel/MapServer/tile/{z}/{y}/{x}",//不穩定
        "geoq-Hydro": "http://thematic.geoq.cn/arcgis/rest/services/ThematicMaps/WorldHydroMap/MapServer/tile/{z}/{y}/{x}",//不穩定
        "geoq-green": "http://thematic.geoq.cn/arcgis/rest/services/ThematicMaps/vegetation/MapServer/tile/{z}/{y}/{x}",//不穩定
        /***
         * Google
         * m 街道
         * s 影像
         */
        "google-vec": "http://www.google.cn/maps/vt?lyrs=m@189&gl=cn&x={x}&y={y}&z={z}",
        "google-img": "http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}"

    };

展示資源

  • 最終效果如下,矩形框內是我們需要獲取的地圖也就是需要爬蟲下載的

1556064758315

加載地圖
點選選擇範圍
將範圍繪製在地圖上
  • 四個座標轉換成四至得到矩形
xsq = "120.22940239501227;30.226915680225147;120.28948387694587;30.146807031535218"

xsqlist = xsq.split(";")

xsq_x_list = []
xsq_y_list = []

for i in range(len(xsqlist)):
    if i % 2 == 0:
        xsq_x_list.append(float(xsqlist[i]))
    else:
        xsq_y_list.append(float(xsqlist[i]))

xsq_x_y_list = []

for x, y in zip(xsq_x_list, xsq_y_list):
    xsq_x_y_list.append([float(x), float(y)])

MINX = min(xsq_x_list)
MAXX = max(xsq_x_list)
MINY = min(xsq_y_list)
MAXY = max(xsq_y_list)

print([MINX, MINY])
print([MINX, MAXY])
print([MAXX, MAXY])
print([MAXX, MINY])
print([MINX, MINY])
  • 地圖顯示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>高德地圖+ol</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.6.5/ol.css"
          integrity="sha256-rQq4Fxpq3LlPQ8yP11i6Z2lAo82b6ACDgd35CKyNEBw=" crossorigin="anonymous"/>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.6.5/ol.js"
            integrity="sha256-77IKwU93jwIX7zmgEBfYGHcmeO0Fx2MoWB/ooh9QkBA="
            crossorigin="anonymous"></script>
    <style>
        #map {
            width: 100%;
            height: 100%;
            position: absolute;
        }
    </style>
</head>


<body>
<div id="map"></div>
<script type="text/javascript">

    
     var gaodeMapLayer = new ol.layer.Tile({
        title: "titile",
        source: new ol.source.XYZ({
            url: mapUrl["tian-vec"]
        })
    });

    var fa = new ol.layer.Vector({
        source: new ol.source.Vector({
            features: [new ol.Feature({
                geometry: new ol.geom.Polygon(
                    [[
                        [120.22940239501227, 30.146807031535218],
                        [120.22940239501227, 30.226915680225147],
                        [120.28948387694587, 30.226915680225147],
                        [120.28948387694587, 30.146807031535218],
                        [120.22940239501227, 30.146807031535218],


                    ]]
                ),
                name: 'pg'
            })]
        }),
    });


    var map = new ol.Map({
        layers: [gaodeMapLayer, fa],
        view: new ol.View({
            center: [120, 30],
            projection: 'EPSG:4326',
            zoom: 10
        }),
        target: 'map'
    });

// 點選地圖用
    map.on('singleclick', function (e) {
        console.log(map.getEventCoordinate(e.originalEvent));

    })

</script>
</body>

</html>

爬蟲開始

1556065317469

  • 根據圖中描述,所需要素爲 x ,y ,z 三者 ,在資源路由中不難看出 xyz 都是作爲未知數

    {"tian-vec": "http://t{0-7}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=a4ee5c551598a1889adfabff55a5fc27"}
    

瀏覽器調試

  • 觀察下圖,我們可以發現右側小圖片中的那塊內容在左側出現

1556065511020

1556065578972

獲取地址

使用同樣的方式獲取右下角地址

地址如何使用?

  1. 不變的是z 在天地圖url中是l ,本文示例l=15

  2. 在地址中x y 存在關係: x 向右增加,y向下增加

    本文x範圍 [ 27326,27333 ]

    本文y範圍[ 13492, 13507 ]

到目前所有參數準備就緒

  • tips: 天地圖的key 需要自己註冊 ,本文已經提供了

1556065642970

代碼怎麼寫?

單個圖片下載

import requests
import os

# 文件存放位置設置
BASE_PATH = os.path.join(os.path.abspath(os.curdir), 'disc')
print(BASE_PATH)

# 簡單反爬蟲 , 可以不寫
headers = {
    "Connection": "keep-alive",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
}

# 單個圖片的參數
x = 27326
y = 13492
z = 15
key = 'a4ee5c551598a1889adfabff55a5fc27'
# 完整url
url = "http://t3.tianditu.gov.cn/DataServer?T=vec_w&x={}&y={}&l={}&tk={}".format(x, y, z, key)
# 保存文件名稱
fileName = os.path.join(BASE_PATH, "x={}y={}z={}.png".format(x, y, z))
# 具體下載操作
if (os.path.exists(fileName)) == False:
    r = requests.get(url=url, headers=headers)
    if r.status_code == 200:
        with open(fileName, 'wb') as f:
            for chunk in r:
                f.write(chunk)

1556066821225

下載成功

多圖下載

import requests
import os
# 文件存放位置設置
BASE_PATH = os.path.join(os.path.abspath(os.curdir), 'disc')
BASE_PATH_res = os.path.join(os.path.abspath(os.curdir), 'result')

# 簡單反爬蟲 , 可以不寫
headers = {
    "Connection": "keep-alive",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
}


def download_pic(x, y, z):
    try:
        # 下載圖片
        key = 'a4ee5c551598a1889adfabff55a5fc27'
        for xi in x:
            for yi in y:
                url = "http://t3.tianditu.gov.cn/DataServer?T=vec_w&x={}&y={}&l={}&tk={}".format(xi, yi, z, key)
                # 保存文件名稱
                fileName = os.path.join(BASE_PATH, "x={}y={}z={}.png".format(xi, yi, z))
                # 具體下載操作
                if (os.path.exists(fileName)) == False:
                    r = requests.get(url=url, headers=headers)
                    if r.status_code == 200:
                        with open(fileName, 'wb') as f:
                            for chunk in r:
                                f.write(chunk)
                    else:
                        print("訪問異常")
    except Exception as e:
        print(e)
        pass
    
    
if __name__ == '__main__':
    x = range(27326 - 1, 27326 + 2)  
    y = range(13492 - 1, 13492 + 2)  
    z = 15
    picSize = 256
    download_pic(x, y, z)

1556067505257

至此我們將一部分圖片下載完成

拼圖

  • 在上面多圖下載結果中我們看到了很多一張張的圖片和我們在地圖上看到的不太一樣,地圖上的是一整張的,所以我們需要將這個圖拼起來構造一張完整的圖,如下圖

1556067632473

  • 我們將圖想象成下圖的形式,只需要知道每一個格子裏面填寫什麼(圖片名稱)

1556067720478

def merge_pic(x, y, z):
    picSize = 256
    try:
        # 構造平圖矩陣
        li = []

        for xi in x:
            lis = []
            for yi in y:
                fileName = os.path.join(BASE_PATH, "x={}y={}z={}.png".format(xi, yi, z))
                lis.append(fileName)

            li.append(lis)

        oca = len(x)
        ocb = len(y)

        toImage = Image.new('RGBA', (oca * picSize, ocb * picSize))

        for i in range(oca):
            for j in range(ocb):
                fromImge = Image.open(li[i][j])
                picx = 256 * i
                picy = 256 * j
                loc = (picx, picy)
                toImage.paste(fromImge, loc)

        toImage.save(os.path.join(BASE_PATH_res, "rs.png"))
        print("構造完成輸出圖片")

    except  Exception as e:
        print(e)
        pass

完整demo

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import requests
from PIL import Image
import os

# 文件存放位置設置
BASE_PATH = os.path.join(os.path.abspath(os.curdir), 'disc')
BASE_PATH_res = os.path.join(os.path.abspath(os.curdir), 'result')

# 簡單反爬蟲 , 可以不寫
headers = {
    "Connection": "keep-alive",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
}


def download_pic(x, y, z):
    try:
        # 下載圖片
        key = 'a4ee5c551598a1889adfabff55a5fc27'
        for xi in x:
            for yi in y:
                url = "http://t3.tianditu.gov.cn/DataServer?T=vec_w&x={}&y={}&l={}&tk={}".format(xi, yi, z, key)
                # 保存文件名稱
                fileName = os.path.join(BASE_PATH, "x={}y={}z={}.png".format(xi, yi, z))
                # 具體下載操作
                if (os.path.exists(fileName)) == False:
                    r = requests.get(url=url, headers=headers)
                    if r.status_code == 200:
                        with open(fileName, 'wb') as f:
                            for chunk in r:
                                f.write(chunk)
                    else:
                        print("訪問異常")
    except Exception as e:
        print(e)
        pass


def merge_pic(x, y, z):
    picSize = 256
    try:
        # 構造平圖矩陣
        li = []

        for xi in x:
            lis = []
            for yi in y:
                fileName = os.path.join(BASE_PATH, "x={}y={}z={}.png".format(xi, yi, z))
                lis.append(fileName)

            li.append(lis)

        oca = len(x)
        ocb = len(y)

        toImage = Image.new('RGBA', (oca * picSize, ocb * picSize))

        for i in range(oca):
            for j in range(ocb):
                fromImge = Image.open(li[i][j])
                picx = 256 * i
                picy = 256 * j
                loc = (picx, picy)
                toImage.paste(fromImge, loc)

        toImage.save(os.path.join(BASE_PATH_res, "rs.png"))
        print("構造完成輸出圖片")

    except  Exception as e:
        print(e)
        pass


if __name__ == '__main__':
    x = range(27326 - 1, 27326 + 2)
    y = range(13492 - 1, 13492 + 2)
    z = 15
    download_pic(x, y, z)
    merge_pic(x, y, z)

本文代碼及可視化代碼均放在 github 歡迎star & fork

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章