目录

前言

代码实现

思路

小结


前言

由于近期经常写报告,开始的时候是把报告写一个汇总文档里,后来要按标题一个一个的拆分,为了方便,特此写了个脚本来拆分

代码实现

import os
from docx import Document
from docx.shared import Inches
from docx.shared import Pt
from docx.shared import Cm
 
#创建一个函数,将文档中所有的图片保存到images文件夹下,图片名以图片的embed属性值命名(即 rId 命名)
def extract_and_save_images_from_docx(doc_path):
    # 加载文档
    doc = Document(doc_path)
 
    # 创建用于存储图片的文件夹
    image_folder = 'images'
    if not os.path.exists(image_folder):
        os.makedirs(image_folder)
 
    # 获取文档中的所有图片
    def find_images(document):
        images = []
        rels = document.part.rels
        for rel in rels.values():
            if 'image' in rel.reltype:
                image_part = rel.target_part
                embed_id = rel.rId
                images.append((image_part, embed_id))
        return images
 
    # 保存图片
    image_list = find_images(doc)
    for i, (image_part, embed_id) in enumerate(image_list):
        image_filename = f'{embed_id}.png'
        image_path = os.path.join(image_folder, image_filename)
        with open(image_path, 'wb') as f:
            f.write(image_part.blob)
 
    print("Images extracted and saved successfully.")
 
 
 
#创建分化文档的函数,新文件名以  标号+标题名命名 ,标号每次匹配到标题自动 +1
def extract_images_from_docx(doc_path):
    # 加载文档
    doc = Document(doc_path)
 
    # 创建新文档
    new_doc = Document()
    doc = Document(doc_path)
    current_title = None
    current_index = 1
    new_doc = None
 
    # 创建用于存储文档的文件夹
    file_folder = '零散'
    if not os.path.exists(file_folder):
        os.makedirs(file_folder)
 
 
 
    # 遍历段落
    for paragraph in doc.paragraphs:
        if paragraph.style.name.startswith('Heading'): #判断是否是标题
            if new_doc is not None:
                file_name = str(current_index) +current_title + '.docx'
                file_path = os.path.join(file_folder, file_name)
                new_doc.save(file_path)
                #new_doc.save(f'{current_index}{current_title}.docx') # 文件名加上序号和标题名命名,每次遇到新标题序号 +1 (注意:文件名长度可能受到操作系统的限制,导致读取失败,有相关问题修改下标题名)
                current_index += 1
            current_title = paragraph.text
            new_doc = Document()
            new_doc.add_paragraph(paragraph.text, style=paragraph.style.name)
        elif new_doc is not None:
            new_paragraph = new_doc.add_paragraph(paragraph.text, style='Normal')
 
            # 遍历段落中的运行元素
            for run in paragraph.runs:
                # 获取运行元素的XML表示
                run_xml = run._r
                # 检查是否包含图片
                if '<w:drawing>' in run_xml.xml:
                    print("found an image1")
                    # 解析图片信息
                    image_start = run_xml.xml.find('<w:drawing>')
                    image_end = run_xml.xml.find('</w:drawing>') + len('</w:drawing>')
                    image_xml = run_xml.xml[image_start:image_end]
 
                    # 获取关联标识符
                    image_id_start = image_xml.find('r:embed="') + len('r:embed="')
                    image_id_end = image_xml.find('"', image_id_start)
                    image_id = image_xml[image_id_start:image_id_end]
                    #print(image_id)
                    image_path = 'images/'+ image_id +'.png'
                    print("image_path=" + image_path)
 
                    #根据image_id,将images文件夹的图片复制到新文档中
                    new_paragraph.add_run().add_picture(image_path, width=Inches(5))
 
 
                if not new_paragraph.runs:  # 如果段落中没有图片,则添加原文本内容
                    new_paragraph.text = paragraph.text
 
    # 保存新文档
    if new_doc is not None:
        file_name = str(current_index) + current_title + '.docx'
        file_path = os.path.join(file_folder, file_name)
        new_doc.save(file_path)
 
 
# 使用示例
extract_and_save_images_from_docx('pp2.docx')#替换你要分化的文档
extract_images_from_docx('pp2.docx')  #替换你要分化的文档

思路

最开始是打算直接用run._element.tag.endswith('drawing'): 来检测段落中是否包含图片的,可惜一直检测不出来。后来想到文档的xml中图片的embed的值是唯一,故先把原始文档的所有图片先导出一份,启用embed 的值作为图片名;最后通过检测run._r.xml检测run中是否包含<w: drawing>来检测是否有图片,并且提取的其中的embed的值,再将对应图片添加进去。

小结

正文字体格式都统一为正文格式了,没有加粗之类的效果(主要是因为文档中有些字体格式不标准化,有的是wps的格式,有的是自定义的)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐