在现有的arcgis在线地图上添加一个SwissTopo WMS层,使用arcgis python API

4665
9
03-09-2021 02:08
JKaelin
通过
新贡献者II

我一直在尝试使用python的arcgis API添加(或移动)一个SwissTopo WMS层到现有的arcgis在线地图。

使用API,我可以使用WMS将一组选定的SwissTopo层作为新地图添加到我的arcgis Online门户。(如果有人感兴趣,我很乐意分享代码。)

我不能添加(或移动)WMS层到另一个地图。

我找不到任何API文档解决这个问题,也没有一个有用的答案后,网络搜索。

我可以在arcgis Online上手动完成上述操作,但我的要求是使用python编写脚本。

有例子或教程可用于处理SwissTopo WMS层与arcgis API为python?也许是木星笔记本?

提前感谢您的回复。

0荣誉
9回复
JoelHempenius3
偶然的因素

首先应该将WMS(层)注册到门户。从那里可以搜索注册图层并将它们添加到任何你想要的地图上。

这段代码应该可以帮助您注册WMS层,脚本有很多选项,我不确定它们是否都适用于您的WMS。

从xml导入GIS请求。使用非常简单的arcgis pro登录,从arcgis pro python控制台运行此脚本,并确保您已登录#inputs wmsurl = 'https://the.wms.server/geoserver/namespace/wms?#应该以?结尾。Mapurl = 'https://the.wms.server/geoserver/namespace/ows?#应该以?结尾。featureinfo = 'https://the.wms.server/geoserver/namespace/ows?#应该以?结尾。capabiltiesurl = wmsurl + 'SERVICE=WMS&request=getcapabilities' #应该以?结尾xmlfile = r'path/to/ yourabiltiesdocumentlocation \wms.xml' portalproxy = None #r'https://your.portal.server/portal/sharing/proxy?# layerdefaults和前缀和后缀thumbnailfile = r'path/to/your/logofile' usethumbnailfromWMS = True downloadcapabilities = True #将此设置为False并将getcapabilities xml保存到指定的位置。可能是有用的,如果你在一个公司代理layerdescriptionpostfix =对这一层的通用文本的defaultaccessInformation = ' CopyrightHolder snippetprefix =“文本插入在layertitle层总结”snippetpostfix =“文本插入层layertitle后总结”layerlicenseinfo = licenseinfo和使用约束去这里defaulttags =”标签,去,这里“useWMSkeywordsAsTags = True #设置这个假如果你只希望默认标签文件夹=没有#“yourfolder”如果downloadcapabilities: resp = requests,则将门户内容更改为具有现有文件夹名称的字符串。get(wmsurl + 'service=wms&request= getcapabilties&version =1.3.0') with open(xmlfile, 'w') as f: f.write(resp.text) if portalproxy is not None: wmsurl = portalproxy + wmsurl mapurl = portalproxy + mapurl featureinfourl = portalproxy + featureinfourl tree = ElementTree.parse(xmlfile) root = tree. geroot () for capability in root.findall('{http://www.opengis.net/wms}Capability'): for rootlayer in capability.findall('{http://www.opengis.net/wms}Layer'): .; #root layer #here we get all supported crs crsresult = [] for crs in rootlayer.findall('{http://www.opengis.net/wms}CRS'): crstext = crs.text if crstext.startswith("EPSG:"): crsresult.append(crstext.lstrip('EPSG:')) for layer in rootlayer.findall('{http://www.opengis.net/wms}Layer'): name = layer.find('{http://www.opengis.net/wms}Name').text title = layer.find('{http://www.opengis.net/wms}Title').text abstract = layer.find('{http://www.opengis.net/wms}Abstract').text if abstract is None: abstract = '' bboxelement = layer.find('{http://www.opengis.net/wms}EX_GeographicBoundingBox') xmin = bboxelement.find('{http://www.opengis.net/wms}westBoundLongitude').text xmax = bboxelement.find('{http://www.opengis.net/wms}eastBoundLongitude').text ymin = bboxelement.find('{http://www.opengis.net/wms}southBoundLatitude').text ymax = bboxelement.find('{http://www.opengis.net/wms}northBoundLatitude').text bbox = '{},{},{},{}'.format(xmin,ymin,xmax,ymax) layertags = defaulttags keywordlist = layer.find('{http://www.opengis.net/wms}KeywordList') if keywordlist is not None: for keyword in keywordlist.findall('{http://www.opengis.net/wms}Keyword'): layertags = layertags+"," + keyword.text attributionelement = layer.find('{http://www.opengis.net/wms}Attribution') accessInformation = defaultaccessInformation if attributionelement is not None: accessInformation = defaultaccessInformation + ',' + attributionelement.find('{http://www.opengis.net/wms}Title').text properties['title'] = title properties['type'] = 'WMS' properties['typeKeywords'] = 'Data, Service, Web Map Service, OGC' properties['tags'] = layertags properties['url'] = wmsurl properties['description'] = abstract + layerdescriptionpostfix properties['accessInformation'] = accessInformation properties['snippet'] = snippetprefix + title + snippetpostfix properties['licenseInfo'] = layerlicenseinfo properties['text'] = '{"title":"WMS","url":"'+wmsurl+'","mapUrl":"'+mapurl+'","version":"1.3.0","layers":[{"name":"'+ name+'","title":"'+title+'","legendURL":"'+ mapurl + 'service=WMS&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer='+name+'","queryable":true}],"copyright":"none","maxHeight":5000,"maxWidth":5000,"spatialReferences":['+','.join(crsresult)+'],"format":null,"featureInfoUrl":"' +featureinfourl+'","featureInfoFormat":"text/html"}' properties['extent'] = bbox properties['thumbnailURL'] = mapurl + 'SERVICE=WMS&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=TRUE&STYLES=&VERSION=1.3.0&LAYERS='+name+'&WIDTH=800&HEIGHT=532&CRS=EPSG:4326&BBOX=50.720978888973335,3.238626318098767,53.59715706128808,7.262998577472529' if usethumbnailfromWMS: thumbnailfile = properties['thumbnailURL'] gis.content.add(properties,thumbnail = thumbnailfile, folder=folder)
乔尔Hempenius。

语言:JavaScript, Python和英语
JKaelin
通过
新贡献者II

非常感谢您的回复。

gis.content.add()方法是我一直在使用的。这将检索到的WMS层放入一个新的映射中,该映射的名称由项目标题指定。

现在,如果我这样做几次,我最终会得到一组“WMS”地图,每个地图都有一组检索到的WMS层。

我想要的是一个地图在arcgis在线,有所有检索到的WMS层集作为层。这可以手工完成。我想写个脚本。

在我看来,你的方法很好地阐述了我正在做的事情(如果你同意的话,我可能会用它来强化我的程序)。然而,它并没有解决我的问题如上所述。

还有别的主意吗?
再次感谢: slightly_smiling_face:


0荣誉
JKaelin
通过
新贡献者II

澄清一下:

您应该首先将WMS(层)注册到您的门户。
是的,这就是我正在做的。这对我很有效。WMS图层在我的传送门上。

从那里可以搜索注册图层并将它们添加到您想要的任何>地图。
这就是我在arcgis API中遇到困难的地方。任何提示将不胜感激。

0荣誉
JoelHempenius3
偶然的因素

这应该可以工作,但还没有测试过

首先,我得到门户网站注册的WMS,我检索url并创建一个新的WMSlayer与该url,然后我添加第一层。

从arcgis。从arcgis.mapping.ogc中导入WMSLayer。wmslayers = gis.content。查询("DataCentraWarmte", item_type="WMS", max_items=5) print (WMSLayer [0].itemid) layer = WMSLayer(WMSLayer [0].url) wm = WebMap() wm.add_layer(layer.layers[0])

如果您可以直接将项目添加到映射中,并让Python api找出该项目包含哪种层,会不会更容易

乔尔Hempenius。

语言:JavaScript, Python和英语
JKaelin
通过
新贡献者II

再次感谢。

不幸的是,使用这个过程仍然没有达到我所需要的,如上所述。

首先,我在你的代码中修复了一个错别字:

Wmslayers = gis.content。search("DataCentraWarmte", item_type="WMS", max_items=5) print (wmslayers[0].itemid) layer = WMSLayer(wmslayers[0].url) wm = WebMap() wm.add_layer(layer) # FIXED

然后我看到输出与我为gis.content.add()选择的WMS“图层”不匹配。发生的事情(对我来说,可能对你的WMS不同)是WMSLayer(wmslayers[0])。url只获得SwissTopo WMS url,没有选择图层,导致我的情况下有数百层被放入地图。

所以还是没有快乐。

我一直在系统地研究各种方法,我尝试过的所有方法都有WMS层的问题: disappointed_face:

我开始认为这可能是ESRI的一个特性: winking_face:
希望我错了。

0荣誉
JoelHempenius3
偶然的因素

(如果你同意的话,我可能会用它来强化我的程序)

是的,请窃取我的代码: slightly_smiling_face:

我的最后一个代码示例并不是最好的。我知道我必须对WMS层中的图层对象做些什么,但不是这样。

如果您想要WMS中所有层的子集,您应该使用这个。这次我测试了我的代码:

这个WMS有三层。我只希望第一个在我的地图中可见

joelhempenius3_3 - 1615395688395. - png

joelhempenius3_1 - 1615395341942. - png

使用这行代码,我用一个只包含第一层的新列表覆盖WMS层(wm.layers[0])中的层列表

wm.layers[0]。[wm.layers[0].layers[0]]

这给了我这个:

joelhempenius3_0 - 1615395267831. - png

现在,当我跑的时候:

wm.update ()

地图被保存,只有剩下的图层在地图查看器中可见

joelhempenius3_2 - 1615395550360. - png

希望这对你有所帮助

乔尔Hempenius。

语言:JavaScript, Python和英语
JKaelin
通过
新贡献者II

再次感谢你的建议。使用WMSlayer。图层属性是一个潜在的解决方案,但显然在webmap中也需要设置图层索引(?)。然而,WMSlayer没有任何与之相关的方法。

我现在已经用Python的arcgis API为arcgis Online做了大量的WMS层处理测试。目前我的结论是:
- WMS层可以作为内容创建
没有找到一个实用的方法来给webmap添加WMS图层
WMS层的文档、API方法和异常处理都是初级的。

欢迎出席论坛的ESRI开发人员(希望如此)做出回应。

下面是我的工作代码片段。

#测试检索WMS层,并把它们放到arcgis在线门户网站的webmap上。从arcgis中导入gis。从arcgis.mapping.ogc中导入WMSLayer import json gis = gis ("https://poyry.maps.arcgis.com/", USERNAME, PASSWD) #检索WMS图层spatialReferences =[2056, 2400, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3021, 3031, 3032, 3033, 3035, 3785, 3857, 4326, 30061, 30062, 900913, 3152, 30063, 30064] #上面的列表工作->需要研究到底需要什么图层= [{"name": "ch.swisstopo。geologic -eiszeit-lgm", "title": "Letzteiszeitl. "Max。(维克托)500","queryable": True}, {"name": "ch.swisstopo-karto。"skitouren", "title": "Skirouten", "queryable": True}] text_layers = {"title": "SwissTopo", "url": "http://wms.geo.admin. "ch/", "version": "1.3.0", "layers": layers, "spatialReferences": "spatialReferences", "format": None, "featureInfoFormat": "text/html"} item={'title':'SwissTopo_WMS_testing', 'description':'SwissTopo_testing2', 'tags':'wms', 'type':' wms', 'url':'http://wms.geo.admin. sh "。ch/', 'extent': {'xmin': 5.83581, 'ymin': 45.65916, 'xmax': 10.97931, 'ymax': 47.86991}, #不工作'text': json.dumps(text_layers)} swisstopo_testing_wms = gis.content.add(item_properties=item) print("swisstopo_testing_wms: ", swisstopo_testing_wms) display(swisstopo_testing_wms) #结果在一个webmap层下分组了2个WMS层,OK #将WMS层放到webmap上#尝试#1使用.add_layer() -> NG since swisstopo_testing_wms。url是一般SwissTopo层层= WMSLayer (swisstopo_testing_wms.url) wm = WebMap () wm.add_layer(层)wm_item_properties ={“标题”:“WMS_test”,“片段”:“使用Python API创建的地图”,“标签”:“Python”,}wm.save (wm_item_properties) #将所有705 SwissTopo层(!)到webamp门户# 2 #尝试使用.publish () - > NG content.publish()方法没有对WMS # swisstopo_htesting_feaure_layer_item = swisstopo_testing_wms磨破。publish(# publish_parameters={'file_type':"WMS"}) # ValueError:必须提供一个file_type,数据格式不被识别#尝试#3使用WMSlayer。在地图查看器wm.layers[0]中显示layers属性-> NG为错误层。Layers = wm.layers[0]。#wm.update() # RuntimeError: Item object missing,如果你正在创建一个新的web地图项目,你应该使用' save() '方法??wm.save(wm_item_properties) #结果是一个webmap图层条目,它在Overview中正确显示,#然而Map Viewer显示错误的图层!

0荣誉
JoelHempenius3
偶然的因素

我完全同意你的结论。也许埃斯里的人能帮我看看?@AndrewChapkowski

乔尔Hempenius。

语言:JavaScript, Python和英语
0荣誉
achapapkowski
通过
新贡献者II

我会把它添加到待办事项中,以便提交到董事会。

感谢您提供的所有代码和问题的描述。ArcGIS API团队将会关注下个月发布的Post 1.8.5版本。