前面有一篇文章《基于ArcGIS的python编程 7.获取面区域渔网网格的一组对角坐标》写到获取渔网网格的对角坐标就是应用百度地图API的矩形查询功能,爬取某区域的POI数据。经过这段时间的努力,终于把百度地图上梅州市所有POI数据(程序顺利跑完,可能会因为程序设计的问题,少部分POI可能会缺失)爬取下来并分类保存到Excel表格中,如图1,Excel表格的格式如图2。图1 Excel表格图2 Excel表格结构
这篇文章就是着重说明POI点的处理,不涉及爬取的过程;首先利用程序根据Excel表格批量生成点shp类型的数据;因为从网格坐标的获取中可以知道,有些与梅州相交的网格是跨区域的如图2,所以爬取的POI点不在梅州市范围内,所以对点的shp数据进行批量裁剪,获得只在梅州范围内的POI。图3 网格
首先比较传统的Excel表格生成shp数据在Arcmap里有现成的工具;点击工具栏的添加数据图标→选择Excel表格如图4→选择选择Excle表格下的sheet表→在图层管理窗口选中刚刚添加的表格鼠标右键→显示XY数据→选中事件右键→数据→导出数据;刚刚开始我也是用这种方法的,如果是一两个表,很快就可以完成,但是有很多个表的话,这样重复的工作还是挺无聊的,然后就想偷懒一下,自己写了一个简单的批量生成点的程序。图4 导入Excel表格
根据Excel批量生成点数据
程序的大概思路如下:选择一个或者多个表→根据表名,新建点要素类(CreateFeatureclass_management()函数)→读取Excel表格的列名,作为点要素类的字段名→根据列名给点要素添加字段(AddField_management()函数)→利用插入游标插入点,遍历Excel表格,写入字段信息。
完整代码如下:
#coding=utf-8
import arcpy
import xlrd
import time
in_table=arcpy.GetParameterAsText(0) #输入的表格,一个或者多个类型为任意值
savepath=arcpy.GetParameterAsText(1) #保存的路径,类型为文件夹(点数据名与表名一致
spatial=arcpy.GetParameterAsText(2) #参考坐标系,可以自己导入或者新建
tablename=[]
tablepaths=in_table.split(';') #获得表路径列表
for path in tablepaths:
name=path.split('\\')[-1].split('.')[0]
tablename.append(name) #通过简单的字符串处理,获得表名并放在表名列表中
for name in tablename:
#利用表名,根据CreateFeatureclass_management()函数新建一个点要素类
if arcpy.Exists(savepath + '\\' + name + '.shp')==False:
arcpy.CreateFeatureclass_management(savepath,name,'POINT','','','',spatial)
else:
pass
try:
for table in tablepaths:
#根据表路径,读取表里的内容
featurename=table.split('\\')[-1].split('.')[0]
data=xlrd.open_workbook(table)
sh=data.sheets()[0]
ziduanNamelist=sh.row_values(0)#获得列名,即点数据的字段名
for ziduan in ziduanNamelist:
try:
#利用AddField_management()函数为刚刚创建的点要素添加字段
arcpy.AddField_management(savepath+'\\'+featurename+'.shp',ziduan,'TEXT')
except:
pass
#time.sleep(0.5)#设置睡眠时间,因为我软件的问题,太快了总是崩溃
rownum=sh.nrows #获得表格的行数
#接下来读取Excle表格的内容,利用插入游标给上面新建的点要素类插入数据(row)
Insercur = arcpy.InsertCursor(savepath + '\\' + featurename + '.shp')
for r in range(1,rownum):
newpnt=arcpy.Point() #新建一个点
#获得点的xy坐标并赋值给点的XY属性,
# sh.cell(r,c).value,这里的r,c索引要根据你自己表格的格式设置
newpnt.X=float(str(sh.cell(r,2).value))
newpnt.Y=float(str(sh.cell(r,1).value))
pointGeo=arcpy.PointGeometry(newpnt)
newrow = Insercur.newRow() #插入游标新建行row
newrow.shape=pointGeo
for c in range(0,len(ziduanNamelist)):
#遍历Excle表格,并把对应的内容赋值给点字段
newrow.setValue(ziduanNamelist[c],sh.cell(r,c).value)
Insercur.insertRow(newrow) #插入row
except Exception as e:
#异常捕获,用于调试
print e.message
arcpy.AddError(e.message)图5 批量生成点数据工具参数属性图6 点生成后的效果
批量裁剪,获取梅州区域内的POI
传统的思路就是一个点数据,一个面数据,利用裁剪工具一个一个的进行裁剪,也可以获得区域内的POI;批量裁剪的思路参考一篇文章《Arcpy:栅格批量裁剪工具制作(01)》,内容大同小异,只是换了一个函数而已。
完整代码如下:
# coding=UTF-8
import arcpy
in_point = arcpy.GetParameterAsText(0) #点数据,一个或多个
point_paths = in_point.split(';')
in_feature = arcpy.GetParameterAsText(1) #裁剪要素(面区域)
feature_paths = in_feature.split(';')
out_file = arcpy.GetParameterAsText(2) #保存路径,名字与裁剪前相同
for point_layer in point_paths:
name2 = point_layer.split('\\')[-1].split('.')[0]
out_layer=out_file+'\\'+name2
arcpy.Clip_analysis(point_layer, in_feature, out_layer)
工具参数属性如下:图7 批量裁剪工具参数属性图8 裁剪后的POI数据
总结:
如果还想偷懒的话,可以把这两个工具结合在一起,这里不再阐述,有兴趣的可以自己去弄一下。批量生成点数据的程序虽然可以成功跑完,可是感觉有点慢,虽然中间省了很多人工的步骤,不过感觉也没比传统的方法快多少,甚至更加慢了。不过这也不失为一种新的尝试。至于优化,后面有时间再去完善一下,如果您有好的方法或者什么建议,欢迎交流!
专栏文章会同步到微信公众号【GIS学习交流】
欢迎大家关注公众号一起交流,一起学习,一起进步!