python讀取數據庫PostgreSQL導出shapefile(shp)文件

1.現有數據和目標成果

1.1現有數據

源數據保存在數據庫中,使用的數據庫管理軟件是PostgreSQL。

本質上來說,數據存儲在數據庫中是以記錄存儲在表(table)上實現的,在shapefile中也是以記錄的形式存在屬性表(dbf)。所以數據庫中表的列(字段)可以與dbf表的列一一對應。數據庫中數據形式大致如下:

 

1.2目標成果

衆所周知,shapefile是ESRI公司制定的GIS數據的一種格式,一個正常的shapefile至少包括三部分:shp、dbf和shx。有關於shp文件等一系列說明,可以參考我之前的博客——shp系列,鏈接是

https://blog.csdn.net/Fan_z_0802/article/details/85078059

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 psycopg2
from 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查看效果,調試代碼。

 

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