python讀取excel中圖片疯搅,并格式化輸出

python讀取excel中圖片,并格式化輸出

讀取excel中的圖片并格式化輸出健爬,發(fā)現(xiàn)網(wǎng)上并沒有python的解決方案控乾,
都是解壓遍歷圖片,并不能滿足需求娜遵,因此有了下面的方案 
該代碼支持格式化輸出excel圖片文本蜕衡,并可以指定圖片輸出方式,(圖片路徑 / 圖片base64編碼)

步驟

  • 復(fù)制并修改excel文件后綴為zip 格式
  • 解壓zip文件
  • 遍歷/xl/media 下圖片设拟,獲取路徑慨仿,base64等信息
  • 解析 /xl/drawings/ 下 xml文件久脯,獲取圖片在表格中的位置
  • 處理表格,并格式化輸出excel文本及圖片等信息

待處理excel表格

img1.png

處理后結(jié)果

2.png

代碼

# -*- coding: utf-8 -*- 
"""
Project: spider
Creator: zhangx
Create time: 2020-05-23 15:23
Introduction:  讀取含有圖片的excel文件镰吆, 并按照 字典返回帘撰,文本、圖片信息
    復(fù)制excel 并重命名為zip 文件万皿,解壓zip 文件摧找,圖片在 /xl/media 文件夾下,遍歷該文件夾獲得圖片路徑牢硅,
    圖片在excel表格的位置信息保存在蹬耘,/xl/drawings的文件夾下,根據(jù)工作簿的索引保存
    解析xml文件减余,根據(jù) 行列獲取位置综苔,圖片索引根據(jù) rId 屬性值,如rId2 == image2
可以更進(jìn)一步位岔,優(yōu)化:
    1休里, 可以將重命名解壓,等操作在內(nèi)存中進(jìn)行赃承, 這樣可以免去每次都要生成zip 文件妙黍,及解壓包
    2, 如果不在內(nèi)存中解壓瞧剖,應(yīng)當(dāng)每次運(yùn)行后刪除拭嫁,zip文件,及解壓包
    3抓于, 如果多個(gè)工作簿中含有圖片做粤, 可以/xl/drawings/drawing2.xml 及增加通過sheet索引讀取圖片位置信息
"""
import base64
import re
import xml.dom.minidom as xmldom
import os
import zipfile
import shutil
import xlrd


# 判斷是否是文件和判斷文件是否存在
def isfile_exist(file_path):
    if not os.path.isfile(file_path):
        print("It's not a file or no such file exist ! %s" % file_path)
        return False
    else:
        return True


# 復(fù)制并修改指定目錄下的文件類型名,將excel后綴名修改為.zip
def copy_change_file_name(file_path, new_type='.zip'):
    if not isfile_exist(file_path):
        return ''

    extend = os.path.splitext(file_path)[1]  # 獲取文件拓展名
    if extend != '.xlsx' and extend != '.xls':
        print("It's not a excel file! %s" % file_path)
        return False

    file_name = os.path.basename(file_path)  # 獲取文件名
    new_name = str(file_name.split('.')[0]) + new_type  # 新的文件名捉撮,命名為:xxx.zip

    dir_path = os.path.dirname(file_path)  # 獲取文件所在目錄
    new_path = os.path.join(dir_path, new_name)  # 新的文件路徑
    if os.path.exists(new_path):
        os.remove(new_path)
    shutil.copyfile(file_path, new_path)
    return new_path  # 返回新的文件路徑怕品,壓縮包


# 解壓文件
def unzip_file(zipfile_path):
    if not isfile_exist(zipfile_path):
        return False

    if os.path.splitext(zipfile_path)[1] != '.zip':
        print("It's not a zip file! %s" % zipfile_path)
        return False

    file_zip = zipfile.ZipFile(zipfile_path, 'r')
    file_name = os.path.basename(zipfile_path)  # 獲取文件名
    zipdir = os.path.join(os.path.dirname(zipfile_path), str(file_name.split('.')[0]))  # 獲取文件所在目錄
    for files in file_zip.namelist():
        file_zip.extract(files, os.path.join(zipfile_path, zipdir))  # 解壓到指定文件目錄

    file_zip.close()
    return True


# 讀取解壓后的文件夾,打印圖片路徑
def read_img(zipfile_path):
    img_dict = dict()
    if not isfile_exist(zipfile_path):
        return False

    dir_path = os.path.dirname(zipfile_path)  # 獲取文件所在目錄
    file_name = os.path.basename(zipfile_path)  # 獲取文件名
    pic_dir = 'xl' + os.sep + 'media'  # excel變成壓縮包后巾遭,再解壓肉康,圖片在media目錄
    pic_path = os.path.join(dir_path, str(file_name.split('.')[0]), pic_dir)

    file_list = os.listdir(pic_path)
    for file in file_list:
        filepath = os.path.join(pic_path, file)
        print(filepath)
        img_index = int(re.findall(r'image(\d+)\.', filepath)[0])
        img_base64 = get_img_base64(img_path=filepath)
        img_dict[img_index] = dict(img_index=img_index, img_path=filepath, img_base64=img_base64)
    return img_dict


# 獲取img_base64
def get_img_base64(img_path):
    if not isfile_exist(img_path):
        return ""
    with open(img_path, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        s = base64_data.decode()
        return 'data:image/jpeg;base64,%s' % s


def get_img_pos_info(zip_file_path, img_dict, img_feature):
    """解析xml 文件,獲取圖片在excel表格中的索引位置信息"""
    os.path.dirname(zip_file_path)
    dir_path = os.path.dirname(zip_file_path)  # 獲取文件所在目錄
    file_name = os.path.basename(zip_file_path)  # 獲取文件名
    xml_dir = 'xl' + os.sep + 'drawings' + os.sep + 'drawing1.xml'
    xml_path = os.path.join(dir_path, str(file_name.split('.')[0]), xml_dir)
    image_info_dict = parse_xml(xml_path, img_dict, img_feature=img_feature)  # 解析xml 文件灼舍, 返回圖片索引位置信息
    return image_info_dict


# 重命名解壓獲取圖片位置吼和,及圖片表格索引信息
def get_img_info(excel_file_path, img_feature):
    if img_feature not in ["img_index", "img_path", "img_base64"]:
        raise Exception('圖片返回參數(shù)錯(cuò)誤, ["img_index", "img_path", "img_base64"]')
    zip_file_path = copy_change_file_name(excel_file_path)
    if zip_file_path != '':
        if unzip_file(zip_file_path):
            img_dict = read_img(zip_file_path)  # 獲取圖片骑素,返回字典炫乓,圖片 img_index, img_index, img_path末捣, img_base64
            image_info_dict = get_img_pos_info(zip_file_path, img_dict, img_feature)
            return image_info_dict
    return dict()


# 解析xml文件并獲取對(duì)應(yīng)圖片位置
def parse_xml(file_name, img_dict, img_feature='img_path'):
    # 得到文檔對(duì)象
    image_info = dict()
    dom_obj = xmldom.parse(file_name)
    # 得到元素對(duì)象
    element = dom_obj.documentElement

    def _f(subElementObj):
        for anchor in subElementObj:
            xdr_from = anchor.getElementsByTagName('xdr:from')[0]
            col = xdr_from.childNodes[0].firstChild.data  # 獲取標(biāo)簽間的數(shù)據(jù)
            row = xdr_from.childNodes[2].firstChild.data
            embed = \
            anchor.getElementsByTagName('xdr:pic')[0].getElementsByTagName('xdr:blipFill')[0].getElementsByTagName(
                'a:blip')[0].getAttribute('r:embed')  # 獲取屬性
            image_info[(int(row), int(col))] = img_dict.get(int(embed.replace('rId', '')), {}).get(img_feature)

    sub_twoCellAnchor = element.getElementsByTagName("xdr:twoCellAnchor")
    sub_oneCellAnchor = element.getElementsByTagName("xdr:oneCellAnchor")
    _f(sub_twoCellAnchor)
    _f(sub_oneCellAnchor)
    return image_info


def read_excel_info(file_path, img_col_index, img_feature='img_path'):
    """
    讀取包含圖片的excel數(shù)據(jù)侠姑, 并返回列表
    :param file_path:
    :param img_col_index: 圖片索引列,list
    :param img_feature: 指定圖片返回形式 img_index", "img_path", "img_base64"
    :return:
    """
    img_info_dict = get_img_info(file_path, img_feature)
    book = xlrd.open_workbook(file_path)
    sheet = book.sheet_by_index(0)
    head = dict()
    for i, v in enumerate(sheet.row(0)):
        head[i] = v.value
    info_list = []
    for row_num in range(sheet.nrows):
        d = dict()
        for col_num in range(sheet.ncols):
            if row_num ==0:
                continue
            if 'empty:' in sheet.cell(row_num, col_num).__str__():
                if col_num in img_col_index:
                    d[head[col_num]] = img_info_dict.get((row_num, col_num))
                else:
                    d[head[col_num]] = sheet.cell(row_num, col_num).value
            else:
                d[head[col_num]] = sheet.cell(row_num, col_num).value
        if d:
            info_list.append(d)
    return info_list


if __name__ == '__main__':
    i = read_excel_info(r'C:\Users\a\Desktop\匯豐銀行信用卡-賬戶&鏈接信息-20200521.xlsx', img_col_index=[5, 6])
    from pprint import pprint
    pprint(i)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載箩做,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者结借。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市卒茬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咖熟,老刑警劉巖圃酵,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異馍管,居然都是意外死亡郭赐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門确沸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捌锭,“玉大人,你說我怎么就攤上這事罗捎」矍” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵桨菜,是天一觀的道長(zhǎng)豁状。 經(jīng)常有香客問我,道長(zhǎng)倒得,這世上最難降的妖魔是什么泻红? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮霞掺,結(jié)果婚禮上谊路,老公的妹妹穿的比我還像新娘。我一直安慰自己菩彬,他們只是感情好缠劝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骗灶,像睡著了一般剩彬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矿卑,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天喉恋,我揣著相機(jī)與錄音,去河邊找鬼。 笑死轻黑,一個(gè)胖子當(dāng)著我的面吹牛糊肤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播氓鄙,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼馆揉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了抖拦?” 一聲冷哼從身側(cè)響起升酣,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎态罪,沒想到半個(gè)月后噩茄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡复颈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年绩聘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耗啦。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凿菩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出帜讲,到底是詐尸還是另有隱情衅谷,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布似将,位于F島的核電站会喝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏玩郊。R本人自食惡果不足惜肢执,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望译红。 院中可真熱鬧预茄,春花似錦、人聲如沸侦厚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刨沦。三九已至诗宣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間想诅,已是汗流浹背召庞。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工岛心, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篮灼。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓忘古,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親诅诱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子髓堪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354