自制工具將excel檔案批量匯入到mongodb
阿新 • • 發佈:2018-12-15
使用方法
- 下載此工具(度盤 密碼: sbv6),這是一個exe檔案,雙擊可直接執行
- 將這個工具放到你要處理的表格所在的目錄,比如上圖中有一個年級表的示例檔案
- 確保已啟動mongodb服務
- 雙擊指令碼工具,啟動控制檯,會提示你輸入要連線/建立的資料庫名以及表格所在路徑(留空則預設會檢查當前目錄以及當前目錄下的“data”資料夾(如果有的話)),由於我們已經把指令碼和表格放在了同一目錄下,所以這裡直接回車即可
- 等待程式執行完畢後,按任意鍵退出控制檯
- 在mongo compass中可以檢視資料庫被更新
注意事項
- 工具可能會被殺軟誤識別為病毒,如果覺得不安全的話,可以自己下載python原始碼(見本文附錄)並自行打包成可執行工具(方法可參考
- 在啟動檔案前,請確保MongoDB服務已啟動(提示:命令列輸入
mongod --dbpath $your_db_path$
啟動) - 預設會把檔名作為表名錄入
- 暫不支援判斷資料庫或表是否已存在,為了您的安全,請自行確保該資料庫或表沒有被覆蓋的風險
- 該指令碼預設會檢查當前所在目錄是否有名為“data”的資料夾,如果有的話,會將裡面的檔案作為所有要入庫的excel;沒有的話會將當前目錄中的所有表格型別的檔案(“.xlsx”以及“.xls”字尾)作為待入庫的表格物件。如有其他需求(例如你的表格檔案位於其他盤下的某個目錄裡),請在指令碼啟動後根據控制檯提示填寫你的自定義目錄的絕對路徑
- 暫不支援處理“.csv”字尾的表格檔案
- 指令碼處理完成後,會提示你按任意鍵退出指令碼控制檯
附錄:python原始碼
import pymongo
import xlrd
import os
import re
def main(db_name, read_dir='data/'):
"""使用說明
excel一鍵轉mongo刪減版說明(for redevelopment):
1. 去除了自定義日誌模組lk_logger
2. 開發者請安裝pymongo,xlrd模組
功能說明:
1. 支援批量檔案處理
2. 指令碼啟動後會彈出控制檯,會詢問你要匯入到哪個資料庫(輸入資料庫名稱即可)
3. 指令碼會預設查詢目錄下的表格檔案,或者你也可以自定義某個絕對路徑的目錄作為引數傳入
注意事項:
1. 在啟動檔案前,請確保MongoDB服務已啟動(提示:命令列輸入"mongod --dbpath $your_db_path$"啟動)
2. 預設會把檔名作為表名錄入
3. 暫不支援判斷資料庫或表是否已存在,為了您的安全,請自行確保該資料庫或表沒有被覆蓋的風險
4. 該指令碼預設會檢查當前所在目錄是否有名為"data"的資料夾,如果有的話,會將裡面的檔案作為所有要入庫的excel;沒有的話會將當前目錄中的所有
表格型別的檔案(xlsx以及xls字尾)作為待入庫的表格物件.如有其他需求(例如你的表格檔案位於其他盤下的某個目錄裡),請在指令碼啟動後根據控制檯
提示填寫你的自定義目錄的絕對路徑
5. 暫不支援處理".csv"字尾的表格檔案
6. 指令碼處理完成後,會提示你按任意鍵退出指令碼控制檯
:param db_name: str. 要連線/建立的資料庫名稱
:param read_dir: str. 要讀取的資料夾路徑,可以傳入相對路徑或絕對路徑,路徑名末尾加不加斜槓都可以
:return:
"""
# 連線/建立資料庫
client = pymongo.MongoClient(host='localhost', port=27017) # 首先啟動客戶端
db = client[db_name] # 然後連線/建立資料庫
# while True: # 等待使用者輸入命令,預設會使用表格的檔名作為待會兒要建立的表的名稱
# cmd = input('would you want to set filename to be collection name? (y/n)')
# if cmd == 'y':
# break
# elif cmd == 'n':
# pass
# else:
# continue
# 這裡指令碼預設會查詢指令碼所在的資料夾有沒有名為"data"的資料夾,如果有的話,則將data裡面的檔案認為是要處理的表格
# 如果找不到"data"資料夾,則指令碼會認為使用者把表格放在了與指令碼同級的資料夾中,則指令碼會在同級蒐集所有的檔案
# (後面會自動排除掉型別非表格的檔案,所以不要擔心指令碼把自己當成一個表格)
if os.path.exists(read_dir):
if read_dir[-1] != '/':
read_dir += '/'
# '../my_custom_data_folder' --> '../my_custom_data_folder/'
# 這裡做一個小處理,如果傳入的路徑引數末尾不含斜槓,則加上一個斜槓
# 之所以這樣做,是為了在後面開啟workbook路徑的時候不會出錯
else:
read_dir = os.path._getfullpathname(os.path.abspath(__file__))
# --> r'E:\workspace\smart_tools\excel_2_mongodb_tool\main_app.py'
read_dir = read_dir.replace('\\', '/')
# --> 'E:/workspace/smart_tools/excel_2_mongodb_tool/main_app.py'
read_dir = re.sub(r'(/)(?!.*\1).+$', '', read_dir) + '/'
# --> 'E:/workspace/smart_tools/excel_2_mongodb_tool/'
print('current directory = {}'.format(read_dir))
"""注意事項:
獲取當前指令碼所在的目錄:
# 不要用:
read_dir = os.path.dirname(__file__)
# 該語句在python中可以實現,但在打包成exe後,使用該語句會返回空值錯誤
# 要用:
read_dir = os.path._getfullpathname(os.path.abspath(__file__))
read_dir = re.sub(r'(/)(?!.*\1).+$', '', read_dir)
# 先獲取檔案的絕對路徑(含指令碼檔名),再把指令碼名用正則去掉
另外需要注意的是正則的使用:
# e.g. read_dir = 'E:/workspace/smart_tools/excel_2_mongodb_tool/main_app.py'
# 不要用:
read_dir = re.sub(r'/.+$', '', read_dir)
# 正則預設會貪婪匹配,該語句會匹配到第一個斜槓,結果會返回"E:"
# 要用:
read_dir = re.sub(r'(/)(?!.*\1).+$', '', read_dir)
# 該語句會匹配斜槓最後一次出現的位置,從而正確地去除指令碼名,結果會返回"E:/workspace/smart_tools/excel_2_mongodb_tool"
當然如果覺得正則麻煩的話,也可以用:
# e.g. read_dir = 'E:/workspace/smart_tools/excel_2_mongodb_tool/main_app.py'
read_dir = '/'.join(read_dir.split('/')[:-1]) + '/'
# --> 'E:/workspace/smart_tools/excel_2_mongodb_tool/'
"""
files = os.listdir(read_dir) # --> ['a.xlsx', 'b.xls', 'c.xlsx', ...]
if not files:
pring('[W] no excel found in your directory!')
raise AttributeError
for file in files:
if '.' in file and 'xls' in file[-4:]: # 目前僅支援xlsx和xls型別的檔案的識別
print('------------------------------------------------ file = {}'.format(file)) # 列印一條分割線
table_name = file.split('.')[0] # 'a.xlsx' --> ['a', 'xlsx'] --> 'a'
current_table = db[table_name] # 以檔名為表名,建立一張表
workbook = xlrd.open_workbook(read_dir + file) # --> open_workbook('data/a.xlsx')
sheet = workbook.sheet_by_index(0) # 獲得sheet1的資料
rows_tag = sheet.row_values(0) # 獲得第一行的表格資料,一般來說這就是標題頭,可以作為字典的鍵名使用
print('rows_tag = {}'.format(rows_tag))
for j in range(1, sheet.nrows): # 開始遍歷表格的每一行,將每一行的資料作為一個物件錄入到這張表中
row_data = dict(zip(rows_tag, sheet.row_values(j)))
"""example
舉個例子說明一下zip(list, list)的作用:
a = zip(['iii', 'jjj', 'kkk'], ['uuu', 'vvv', 'www', 'xxx', 'yyy', 'zzz'])
print(a) # --> <zip object at 0x0000019F876A8C48>
print(dict(a)) # --> {'iii': 'uuu', 'jjj': 'vvv', 'kkk': 'www'}
print(list(a)) # --> [('iii', 'uuu'), ('jjj', 'vvv'), ('kkk', 'www')]
所以經過此步驟我們得到的row_data為一個字典物件:
{
'name' : 'Mark',
'gender': 'male',
'age' : '23',
...
}
pymongo可以接受dict型別的資料,所以接下來直接將row_data插入到表中即可
"""
current_table.insert_one(row_data)
input('script executed over, press anykey to leave... ')
if __name__ == '__main__':
my_db = input('please input the db name which would be created or connected to: ')
my_data_path = input("please input the data path (press enter to use default path: 'data/'): ")
if my_data_path:
main(my_db, my_data_path)
else:
main(my_db)