本文共 4382 字,大约阅读时间需要 14 分钟。
1.现有数据和目标成果
1.1现有数据
源数据保存在数据库中,使用的数据库管理软件是PostgreSQL。
本质上来说,数据存储在数据库中是以记录存储在表(table)上实现的,在shapefile中也是以记录的形式存在属性表(dbf)。所以数据库中表的列(字段)可以与dbf表的列一一对应。数据库中数据形式大致如下:
1.2目标成果
众所周知,shapefile是ESRI公司制定的GIS数据的一种格式,一个正常的shapefile至少包括三部分:shp、dbf和shx。有关于shp文件等一系列说明,可以参考我之前的博客——shp系列,链接是
shp文件用ArcMap打开后如下(包括图形和属性表):
2.代码过程
2.1连接数据库获取数据
要获取数据库数据必须要先连接数据库,连接PostgreSQL的方法网上很多参考,也可以参考我源代码的方式。
执行SQL(结构化查询语言),获取数据库要导出数据的表的字段数,以及要导出的记录。
一个简单的示例如下:
'''连接数据获取数据,WHU_Fan,0706'''def getData(): '''databese是要连接数据库的名字,user是访问用户(创建数据库时设置),password是创建数据库的密码,host填localhost,端口为安装数据库时设置的端口''' '''这里是PostgreSQL的连接方法,MySQL也类似,端口可能不一样''' conn = psycopg2.connect(database='test2',user='postgres',password='admin',host='localhost',port='5432') cur = conn.cursor() ''''设置自己的sql语句''' '''例如''' tableName = 'outcome' commandFindColumn = "select COLUMN_NAME from information_schema.COLUMNS where table_name='%s' "% (tableName) '''执行SQL语句获取数据''' cur.execute(commandFindColumn) columnRows = cur.fetchall() '''SQL语句:导出outcome表的全部''' commandFindRecord = "select * from %s order by 相似度 desc"%(tableName) '''执行SQL语句获取数据''' cur.execute(commandFindRecord) recordRows = cur.fetchall() '''提交确认''' conn.commit() '''关闭连接''' cur.close() conn.close() '''返回数据''' return columnRows,recordRows
2.2解析数据
获取的字段变量columnRows,是一个list,顺序的包含数据库对应表的每一个字段。
获取的记录信息recordRows,也是一个list,包含所有满足条件的记录。
2.3写到shp中
1.调用函数连接数据库获取数据
2.创建shp文件
3.创建字段
4.写入图形和属性信息
5.关闭保存文件
代码如下:
'''outcome表导出到shp,WHU_Fan,0706'''def writeToShp(filePath): '''调用连接数据库函数''' columnRows,recordRows = getData() '''创建shp文件w''' w = shapefile.Writer(filePath) '''创建字段,此处可以固定字段,或者灵活字段,根据需求改变''' '''本处字段暂时写固定已知的,可以改写成灵活的''' '''F 代表数值型,C 字符型''' w.field('任务id','F') w.field('来源', 'C') w.field('poi名', 'C') w.field('类型', 'C') w.field('纬度', 'C') w.field('精度', 'C') w.field('地址', 'C') w.field('地理位置', 'C') w.field('抓取时间', 'C') '''添加图形和属性信息''' for recordRow in recordRows: '''将字符型经纬度转化为数值型''' x = float(recordRow[5]) y = float(recordRow[4]) '''创建点状要素,坐标为经纬度''' '''创建其他类型要素类似,输入合理的坐标点即可,详细参考之前博客的shp文件说明''' w.point(x,y) '''创建对应的dbf属性信息,与图形一一对应''' w.record(recordRow[0],recordRow[1],recordRow[2],recordRow[3],recordRow[4],recordRow[5],recordRow[6],recordRow[7],recordRow[8],encoding='UTF-8') w.close()
3.源代码
#encoding:utf-8'''written by WHU_fan,0705'''import shapefile import psycopg2from datetime import datetime'''连接数据库获取数据'''def getData(): conn = psycopg2.connect(database='test2',user='postgres',password='admin',host='localhost',port='5432') cur = conn.cursor() tableName = 'outcome' commandFindColumn = "select COLUMN_NAME from information_schema.COLUMNS where table_name='%s' "%(tableName) cur.execute(commandFindColumn) columnRows = cur.fetchall() '''导出outcome的成果''' commandFindRecord = "select * from %s where poi名2!='' order by 相似度"%(tableName) cur.execute(commandFindRecord) recordRows = cur.fetchall() conn.commit() cur.close() conn.close() return columnRows,recordRows'''outcome表导出到shp'''def writeToShp(filePath): columnRows,recordRows = getData() w = shapefile.Writer(filePath) '''添加字段''' w.field('任务id','F') w.field('来源', 'C') w.field('poi名', 'C') w.field('类型', 'C') w.field('纬度', 'C') w.field('精度', 'C') w.field('地址', 'C') w.field('地理位置', 'C') w.field('抓取时间', 'C') for recordRow in recordRows: x = float(recordRow[5]) y = float(recordRow[4]) w.point(x,y) w.record(recordRow[0],recordRow[1],recordRow[2],recordRow[3],recordRow[4],recordRow[5],recordRow[6],recordRow[7],recordRow[8],encoding='UTF-8') w.close()if __name__ == '__main__': '''获取当前日期,得到一个datetime对象如:(2019, 7, 2, 23, 12, 23, 424000)''' '''#将获取到的datetime对象仅取日期如:2019-7-2''' today = datetime.today() today_date = datetime.date(today) writeToShp('shapefile/point_' + str(today_date)) print('succeed')
4.属性表乱码问题
问题:导出的shp用ArcGIS打开,属性表发生乱码。
解决:
1.python文件编码设为UTF-8 #encoding:utf-8
2.写属性表时编码设为UTF-8 encoding='UTF-8'
3.cmd运行命令(关键):
reg add HKEY_CURRENT_USER\Software\ESRI\Desktop10.2\Common\CodePage /v dbfDefault /t REG_SZ /d UTF-8 /f
5.成果总结
1.导出shp的过程比较简单,主要是使用开源库,不需要从底层写起。
2.创建字段时需要根据字段的属性设置对应编码(“C”,“F”,还是其他)
3.使用ArcGIS查看效果,调试代码。
转载地址:https://blog.csdn.net/Fan_z_0802/article/details/94743094 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!