Python读取excel文件可读取xlsx格式和xls格式可直接读取超链接,读出为字典格式(列表套字典),处理合并单元格的问题
生活随笔
收集整理的這篇文章主要介紹了
Python读取excel文件可读取xlsx格式和xls格式可直接读取超链接,读出为字典格式(列表套字典),处理合并单元格的问题
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
直接上代碼:(代碼有注釋,代碼下方有解釋)
1.可讀取excel中的xlsx格式文件
2.可讀取excel中的xls格式文件
3.可直接讀取網(wǎng)頁上的excel的超鏈接
4.解決有列合并的情況以及行合并的問題,由合并的情況,分別對應(yīng)的填充
5.返回數(shù)據(jù)為 {"Sheet1":[{},{},{}....], "Sheet2":[{},{},{}....]}? ?注意,有的工作表中的名字是自己工作表的名字,這里只舉例
import os from datetime import datetime from pprint import pprint import requests import win32com.client as win32 import xlrd from collections import Counter from fake_useragent import UserAgent from xlrd import xldate_as_tupleclass ReadExcel:"""1.可讀取excel中的xlsx格式文件2.可讀取excel中的xls格式文件3.可直接讀取網(wǎng)頁上的excel的超鏈接讀出的格式為[{},{},{}]。。。每一個字典為,一行對應(yīng)列名的一個字典"""def __init__(self, file_path=None, index=None, header=None, auto_header=False, url=None, headers=None):"""傳入的參數(shù)的解釋:param file_path: (str)如果要讀取的是文件,傳入路徑參數(shù),絕對路徑和相對路徑都可以,兼容性強:param index: (int)選擇第幾行為列名,索引從0開始:param header: (list)傳入列名,要與數(shù)據(jù)列對應(yīng),不建議用,除非表中沒有頭:param auto_header: (bool)自動識別列名:param url: (str)如果要直接讀取url, 直接傳入網(wǎng)頁中excel中的超鏈接:param headers: (dict)如果讀取的超鏈接,有的網(wǎng)站的文件有反爬,所以為了防止需要注意的是,file_path和url只能二選一,意為讀取文件或者超鏈接index、header、auto_header 只需要三選一即可headers 可傳可不傳,不傳時,請求頭只有User-Agent,一般的文件都可以如果你的文件也有反爬的話,建議傳入headers"""self.file_path = file_pathself.url = urlself.headers = headersself.index = indexself.header = headerself.auto_header = auto_header# 判斷文件類型if file_path is not None: # 傳入的是文件if 'xlsx' in file_path: # 如果傳入的文件是 xlsx 文件類型,將xlsx文件類型轉(zhuǎn)化為xlsx# 將原來的文件名,替換成同名不同類型的文件,即xls結(jié)尾的文件(注意這塊直接得到的是文件名,雖然傳入的完整路徑)fileName = os.path.basename(file_path).replace("xlsx", 'xls')# 文件導(dǎo)出的目錄路徑和文件名稱,文件名稱如上export_name = os.path.join(os.path.dirname(os.path.abspath(file_path)), fileName)self.xlsx_to_xls(file_path, export_name) # 開始進行轉(zhuǎn)換self.file_path = export_name # 設(shè)置文件路徑為轉(zhuǎn)換后的文件路徑else:# 如果是xls直接將目錄進行拼接,絕對路徑,并且設(shè)置文件路徑self.file_path = os.path.join(os.path.dirname(os.path.abspath(file_path)), os.path.basename(file_path))else: # 超鏈接if self.headers is None: # 如果沒有傳入請求頭,默認的只有隨機的User-Agentself.headers = {"User-Agent": UserAgent().random}else:# 如果傳入了請求頭,就用該請求頭,用隨機的User-Agent,有就更新,無則加入進去self.headers.update({"User-Agent": UserAgent().random})# 設(shè)置文件路徑為讀取excel超鏈接的文件之后的文件路徑,當(dāng)前路徑,讀取后會刪除文件self.file_path = self.read_url_excel()# formatting_info=True, 防止merged_cells獲取合并的行或者列時為空列表self.workbook = xlrd.open_workbook(self.file_path, formatting_info=True) # 讀取文件self.sheet_names = self.workbook.sheet_names() # 獲取該文件所有的工作表名# 如果index和header都沒有傳入,則設(shè)置index為0,即就是從第一行開始讀取if self.index is None or self.header is not None:self.index = 0def merge_cell(self, sheet_info):""":param sheet_info: 傳入表格的對象:return:返回,有合并的行和列的鍵值對"""merge = {}merge_cells = sheet_info.merged_cellsfor (rlow, rhigh, clow, chigh) in merge_cells:value_mg_cell = sheet_info.cell_value(rlow, clow)if sheet_info.cell(rlow, clow).ctype == 3: # 對讀出來的時間格式進行轉(zhuǎn)換date = datetime(*xldate_as_tuple(value_mg_cell, 0))value_mg_cell = date.strftime('%Y-%m-%d')if rhigh - rlow == 1:# Merge transverse cellsfor n in range(chigh - clow - 1):merge[(rlow, clow + n + 1)] = value_mg_cellelif chigh - clow == 1:for n in range(rhigh - rlow - 1):merge[(rlow + n + 1, clow)] = value_mg_cellreturn mergedef xlsx_to_xls(self, fname, export_name, delete_flag=False):"""將xlsx文件轉(zhuǎn)化為xls文件:param fname: 傳入待轉(zhuǎn)換的文件路徑(可傳絕對路徑,也可傳入相對路徑,都可以):param export_name: 傳入轉(zhuǎn)換后到哪個目錄下的路徑(可傳絕對路徑,也可傳入相對路徑,都可以):param delete_flag: 轉(zhuǎn)換成功后,是否刪除原來的xlsx的文件,默認刪除 布爾類型:return: 無返回值"""excel = win32.gencache.EnsureDispatch('Excel.Application')excel.Visible = Falseexcel.DisplayAlerts = Falseabsolute_path = os.path.join(os.path.dirname(os.path.abspath(fname)), os.path.basename(fname))save_path = os.path.join(os.path.dirname(os.path.abspath(fname)), os.path.basename(export_name))wb = excel.Workbooks.Open(absolute_path)wb.SaveAs(save_path, FileFormat=56) # FileFormat = 51 is for .xlsx extensionwb.Close() # FileFormat = 56 is for .xls extensionexcel.Application.Quit()# 是否刪除原來的數(shù)據(jù)文件if delete_flag:os.remove(absolute_path)def list_dic(self, key_list, value_list):"""兩個列表組成字典:param key_list: 鍵名列表:param value_list: 值列表:return: 返回組成好的字典"""dic = dict(map(lambda x, y: [x, y], key_list, value_list))return dicdef read_url_excel(self):# 請求r = requests.get(url=self.url, headers=self.headers)file_b = r.content# 判斷文件類型, 確定文件類型和名稱if 'xlsx' in self.url:name = 'temp.xlsx'else:name = 'temp.xls'# 保存文件with open(name, 'wb') as f:f.write(file_b)# 判斷是否需要轉(zhuǎn)換,并且確定文件路徑if name == 'temp.xlsx':export_name = 'temp.xls'self.xlsx_to_xls(name, export_name, delete_flag=True)else:export_name = namereturn export_namedef read_excel(self):# 取出所有的工作表的名稱sheet_name_list = self.sheet_namesdic_data = {} # 所有的工作表字典,對應(yīng)該工作表中的數(shù)據(jù),鍵值對形式for sheet_name in sheet_name_list:sheet_simple = [] # 每張工作表# 某個工作表的名稱sheet = self.workbook.sheet_by_name(sheet_name)if sheet.nrows != 0:auto_index = 0 # 自動識別頭在第幾行# 根據(jù)這些數(shù)據(jù)確定,行索引, 可以自己去設(shè)置,更改,按自己的需求flag_list = ['項目名稱', '工程名稱', '許可證號', '證號', '許可證編號', '建設(shè)規(guī)模','施工單位', '勘察單位', '投資額', '勘察單位', '設(shè)計單位', '工程地址', '工程地址', '層數(shù)']# 不要包含這些數(shù)據(jù)的行, 可以自己去設(shè)置,更改,按自己的需求del_list = ['表', '明細', '合計', '總計']if self.auto_header: # 自動識別頭for row_i in range(0, sheet.nrows): # 循環(huán)每一行# 每行所有數(shù)據(jù)連起來的字符串row_data = ''.join([str(r_v) for r_v in sheet.row_values(row_i)]).strip()for del_str in del_list: # 跳過表名if del_str not in row_data:for flag in flag_list:if flag in row_data: # 判斷表頭auto_index = row_iheader = [str(row_value).replace("\n", "").replace(" ", "") for row_value insheet.row_values(auto_index) ifrow_value != '']row_index = auto_index + 1else: # 手動頭或者自定義頭if self.header is None: # 如果沒有傳入表頭,則用index取表頭header = [row_value.replace("\n", "").replace(" ", "") for row_value insheet.row_values(self.index) if row_value != '']row_index = self.indexelse: # 傳入了頭,就用header = self.headerrow_index = 0values_merge_cell = self.merge_cell(sheet) # 這里是調(diào)用處理合并單元格的函數(shù)# row_index 從第幾行開始讀取for i in range(row_index, sheet.nrows): # 開始為組成字典準(zhǔn)備數(shù)據(jù)other_line = []# 處理類型# 可參考 https://www.cnblogs.com/xxiong1031/p/7069006.htmlfor j in range(sheet.ncols):ctype = sheet.cell(i, j).ctype # 表格的數(shù)據(jù)類型cell = sheet.cell_value(i, j)if ctype == 3:# 轉(zhuǎn)成datetime對象date = datetime(*xldate_as_tuple(cell, 0))cell = date.strftime('%Y-%m-%d')other_line.append(cell)# other_line = sheet.row_values(i)# print(other_line)# print(other_line)for key in values_merge_cell.keys():if key[0] == i:if key[1] != '':other_line[key[1]] = str(values_merge_cell[key]).replace("\xa0", "")dic = self.list_dic(header, other_line) # 調(diào)用組合字典的函數(shù),傳入key和value,字典生成# print(self.url)# # pprint(dic)# print(other_line)value_list = [str(v).strip() for v in dic.values()]value_str = ''.join(value_list).strip()pass_list = del_list + flag_listpass_flag = Truefor pass_str in pass_list:if pass_str in value_str:pass_flag = Falsebreakif pass_flag and len(Counter(value_list)) > 1 and value_str != '':try:del dic['序號']except:pass# pprint(dic)sheet_simple.append(dic)dic_data[str(sheet_name)] = sheet_simpleos.remove(self.file_path)return dic_dataif __name__ == '__main__':# 讀取文件,自動識別頭readexcel = ReadExcel(file_path='./abcd/W020200220406735094729 (1).xls', auto_header=True)pprint(readexcel.read_excel())# 讀取超鏈接,自動識別頭,里面有表格合并readexcel_1 = ReadExcel(url='http://zjj.laibin.gov.cn/xxcx/bjgb/P020211122537271486773.xls', auto_header=True)pprint(readexcel_1.read_excel())?注意的幾點問題:
1. 創(chuàng)建類,傳入?yún)?shù)是,如果是文件格式,就用file_path=‘文件路徑’ 的方式,如果是超鏈接的方式 就用 url='超鏈接'??
2. 里面的flag_list 和del_list 根據(jù)需要可以去修改,如果沒有該需求,可以把這個兩個列表設(shè)置我空列表
3.如果你讀出來的excel數(shù)據(jù)有問題,可以隨時聯(lián)系我,私聊或者評論,我會第一時間進行修改,進行更正
謝謝大家
總結(jié)
以上是生活随笔為你收集整理的Python读取excel文件可读取xlsx格式和xls格式可直接读取超链接,读出为字典格式(列表套字典),处理合并单元格的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python的scrapy框架POST方
- 下一篇: Python面试题(三)(爬虫方面)