Python文档处理之实现自动删除Word中带指定底纹颜色的内容

Written by

in

文章目录
  • 该脚本用于自动删除 Word 文档中带有指定底纹颜色的解析内容(如【分析】、【详解】等),同时保留答案块(以【答案】开头的有底纹段落及其后续连续有底纹的答案内容)。文档中所有无底纹的段落(题目描述、选项等)以及答案块内的内容都会被原样保留,其余文档结构(表格、页眉页脚、样式)不受影响。 脚本支持两种输入模式: 处理单个文件:输入一个 .docx 文件路径,输出一个处理后的文件。 批量处理文件夹:输入一个文件夹路径,自动处理该文件夹下所有 .docx 文件,输出到指定文件夹。
  • import os from docx import Document from docx.oxml.ns import qn # ====== 配置参数(请根据您的文档修改)====== TARGET_SHADING_COLOR = ‘F2F2F2’ # 从检测脚本获得的底纹颜色 ANALYSIS_MARKERS = [‘【分析】’, ‘【详解】’, ‘【点睛】’, ‘【错因】’, ‘【避错关键】’] ANSWER_MARKER = ‘【答案】’ DEBUG = True # 打印详细处理信息 # Word命名空间(用于查找元素) NSMAP = {‘w’: ‘http://schemas.openxmlformats.org/wordprocessingml/2006/main’} def has_shading_color(element, color): “””判断元素是否具有指定底纹颜色””” # 使用 findall 并传入命名空间 shading_elements = element.findall(‘.//w:shd’, namespaces=NSMAP) if shading_elements: fill = shading_elements[0].get(qn(‘w:fill’)) if fill: fill_clean = fill.strip().upper().lstrip(‘#’) color_clean = color.strip().upper().lstrip(‘#’) return fill_clean == color_clean return False def is_analysis_start(text): “””是否以解析标记开头””” return any(text.startswith(marker) for marker in ANALYSIS_MARKERS) def collect_all_shaded_paragraphs(doc): “”” 收集文档中所有具有目标底纹颜色的段落(包括文本框内)。 返回列表,每个元素为 (element, text, parent) “”” items = [] # 普通段落 for para in doc.paragraphs: element = para._element if has_shading_color(element, TARGET_SHADING_COLOR): items.append((element, para.text.strip(), element.getparent())) # 文本框段落 for txbx in doc.element.findall(‘.//w:txbxContent’, namespaces=NSMAP): for p in txbx.findall(‘.//w:p’, namespaces=NSMAP): if has_shading_color(p, TARGET_SHADING_COLOR): # 提取文本 texts = [t.text for t in p.findall(‘.//w:t’, namespaces=NSMAP) if t.text] full_text = ”.join(texts).strip() items.append((p, full_text, p.getparent())) return items def process_docx_inplace(input_path, output_path): “”” 在原文档基础上直接删除解析段落,保存到 output_path。 “”” doc = Document(input_path) # 收集所有有底纹的段落 shaded_items = collect_all_shaded_paragraphs(doc) n = len(shaded_items) delete_flags = [False] * n debug_info = [] i = 0 while i < n: element, text, parent = shaded_items[i] if text.startswith(ANSWER_MARKER): # 答案开始,保留 if DEBUG: debug_info.append(f”保留答案开始 {i}: {text[:50]}”) i += 1 # 保留后续连续的有底纹段落,直到遇到解析标记 while i < n: next_element, next_text, _ = shaded_items[i] if is_analysis_start(next_text): break if DEBUG: debug_info.append(f”保留答案内容 {i}: {next_text[:50]}”) i += 1 continue elif is_analysis_start(text): # 解析标记,删除本段及其后连续的有底纹段落(直到下一个答案块或解析标记) if DEBUG: debug_info.append(f”删除解析开始 {i}: {text[:50]}”) delete_flags[i] = True i += 1 while i < n: next_element, next_text, _ = shaded_items[i] if next_text.startswith(ANSWER_MARKER) or is_analysis_start(next_text): break if DEBUG: debug_info.append(f”删除解析内容 {i}: {next_text[:50]}”) delete_flags[i] = True i += 1 continue else: # 有底纹但不是答案也不是解析,删除(通常不会出现) if DEBUG: debug_info.append(f”删除其他有底纹段落 {i}: {text[:50]}”) delete_flags[i] = True i += 1 # 从后往前删除标记的段落元素 for idx in range(n – 1, -1, -1): if delete_flags[idx]: element, _, parent = shaded_items[idx] parent.remove(element) # 保存文档 doc.save(output_path) if DEBUG: print(f”处理文件: {os.path.basename(input_path)}”) print(f”共处理有底纹段落 {n} 个,删除 {sum(delete_flags)} 个”) print(“=== 调试信息 ===”) for info in debug_info[-20:]: # 只打印最后20条,避免过长 print(info) print(“=== 处理完成 ===n”) def process_file_or_folder(input_path, output_path): “”” 自动判断输入是文件还是文件夹: – 如果是文件,处理该文件 – 如果是文件夹,处理文件夹下所有 .docx 文件 “”” if os.path.isfile(input_path): # 单个文件 if not input_path.endswith(‘.docx’): print(“请提供 .docx 文件”) return if os.path.isdir(output_path): base = os.path.basename(input_path).replace(‘.docx’, ‘_已处理.docx’) output_file = os.path.join(output_path, base) else: output_file = output_path process_docx_inplace(input_path, output_file) print(f’处理完成:{os.path.basename(input_path)} -> {output_file}’) elif os.path.isdir(input_path): # 文件夹 if not os.path.exists(output_path): os.makedirs(output_path) for filename in os.listdir(input_path): if filename.endswith(‘.docx’): full_input = os.path.join(input_path, filename) full_output = os.path.join(output_path, filename.replace(‘.docx’, ‘_已处理.docx’)) process_docx_inplace(full_input, full_output) print(f’处理完成:{filename}’) else: print(“输入路径不存在”) if __name__ == ‘__main__’: # ===== 使用示例 ===== # 1. 处理单个文件,输出到指定路径 input_path = r’C:Desktop读书笔记讲义’ output_path = r’C:Desktop读书笔记讲义’ process_file_or_folder(input_path, output_path) 到此这篇关于Python文档处理之实现自动删除Word中带指定底纹颜色的内容的文章就介绍到这了,更多相关Python Word文档处理内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python处理Word文档中的批注(添加、删除) 使用Python在Word文档中添加,删除和回复批注 Python实现在Word中创建,读取和删除列表详解 Python在Word中进行图片添加、替换和删除操作 使用Python实现在Word中添加或删除超链接 通过Python实现在Word中添加和删除书签的操作 详解如何利用Python代码删除Word文档空白行
  • 目录
    • 代码功能概述
    • 文档内容示例
    • 脚本代码 

    该脚本用于自动删除 Word 文档中带有指定底纹颜色的解析内容(如【分析】、【详解】等),同时保留答案块(以【答案】开头的有底纹段落及其后续连续有底纹的答案内容)。文档中所有无底纹的段落(题目描述、选项等)以及答案块内的内容都会被原样保留,其余文档结构(表格、页眉页脚、样式)不受影响。

    脚本支持两种输入模式:

    • 处理单个文件:输入一个 .docx 文件路径,输出一个处理后的文件。
    • 批量处理文件夹:输入一个文件夹路径,自动处理该文件夹下所有 .docx 文件,输出到指定文件夹。

    import os
    from docx import Document
    from docx.oxml.ns import qn
    
    # ====== 配置参数(请根据您的文档修改)======
    TARGET_SHADING_COLOR = 'F2F2F2'  # 从检测脚本获得的底纹颜色
    ANALYSIS_MARKERS = ['【分析】', '【详解】', '【点睛】', '【错因】', '【避错关键】']
    ANSWER_MARKER = '【答案】'
    DEBUG = True  # 打印详细处理信息
    
    # Word命名空间(用于查找元素)
    NSMAP = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
    
    
    def has_shading_color(element, color):
        """判断元素是否具有指定底纹颜色"""
        # 使用 findall 并传入命名空间
        shading_elements = element.findall('.//w:shd', namespaces=NSMAP)
        if shading_elements:
            fill = shading_elements[0].get(qn('w:fill'))
            if fill:
                fill_clean = fill.strip().upper().lstrip('#')
                color_clean = color.strip().upper().lstrip('#')
                return fill_clean == color_clean
        return False
    
    
    def is_analysis_start(text):
        """是否以解析标记开头"""
        return any(text.startswith(marker) for marker in ANALYSIS_MARKERS)
    
    
    def collect_all_shaded_paragraphs(doc):
        """
        收集文档中所有具有目标底纹颜色的段落(包括文本框内)。
        返回列表,每个元素为 (element, text, parent)
        """
        items = []
        # 普通段落
        for para in doc.paragraphs:
            element = para._element
            if has_shading_color(element, TARGET_SHADING_COLOR):
                items.append((element, para.text.strip(), element.getparent()))
        # 文本框段落
        for txbx in doc.element.findall('.//w:txbxContent', namespaces=NSMAP):
            for p in txbx.findall('.//w:p', namespaces=NSMAP):
                if has_shading_color(p, TARGET_SHADING_COLOR):
                    # 提取文本
                    texts = [t.text for t in p.findall('.//w:t', namespaces=NSMAP) if t.text]
                    full_text = ''.join(texts).strip()
                    items.append((p, full_text, p.getparent()))
        return items
    
    
    def process_docx_inplace(input_path, output_path):
        """
        在原文档基础上直接删除解析段落,保存到 output_path。
        """
        doc = Document(input_path)
        # 收集所有有底纹的段落
        shaded_items = collect_all_shaded_paragraphs(doc)
        n = len(shaded_items)
        delete_flags = [False] * n
        debug_info = []
    
        i = 0
        while i < n:
            element, text, parent = shaded_items[i]
            if text.startswith(ANSWER_MARKER):
                # 答案开始,保留
                if DEBUG:
                    debug_info.append(f"保留答案开始 {i}: {text[:50]}")
                i += 1
                # 保留后续连续的有底纹段落,直到遇到解析标记
                while i < n:
                    next_element, next_text, _ = shaded_items[i]
                    if is_analysis_start(next_text):
                        break
                    if DEBUG:
                        debug_info.append(f"保留答案内容 {i}: {next_text[:50]}")
                    i += 1
                continue
            elif is_analysis_start(text):
                # 解析标记,删除本段及其后连续的有底纹段落(直到下一个答案块或解析标记)
                if DEBUG:
                    debug_info.append(f"删除解析开始 {i}: {text[:50]}")
                delete_flags[i] = True
                i += 1
                while i < n:
                    next_element, next_text, _ = shaded_items[i]
                    if next_text.startswith(ANSWER_MARKER) or is_analysis_start(next_text):
                        break
                    if DEBUG:
                        debug_info.append(f"删除解析内容 {i}: {next_text[:50]}")
                    delete_flags[i] = True
                    i += 1
                continue
            else:
                # 有底纹但不是答案也不是解析,删除(通常不会出现)
                if DEBUG:
                    debug_info.append(f"删除其他有底纹段落 {i}: {text[:50]}")
                delete_flags[i] = True
                i += 1
    
        # 从后往前删除标记的段落元素
        for idx in range(n - 1, -1, -1):
            if delete_flags[idx]:
                element, _, parent = shaded_items[idx]
                parent.remove(element)
    
        # 保存文档
        doc.save(output_path)
    
        if DEBUG:
            print(f"处理文件: {os.path.basename(input_path)}")
            print(f"共处理有底纹段落 {n} 个,删除 {sum(delete_flags)} 个")
            print("=== 调试信息 ===")
            for info in debug_info[-20:]:  # 只打印最后20条,避免过长
                print(info)
            print("=== 处理完成 ===n")
    
    
    def process_file_or_folder(input_path, output_path):
        """
        自动判断输入是文件还是文件夹:
        - 如果是文件,处理该文件
        - 如果是文件夹,处理文件夹下所有 .docx 文件
        """
        if os.path.isfile(input_path):
            # 单个文件
            if not input_path.endswith('.docx'):
                print("请提供 .docx 文件")
                return
            if os.path.isdir(output_path):
                base = os.path.basename(input_path).replace('.docx', '_已处理.docx')
                output_file = os.path.join(output_path, base)
            else:
                output_file = output_path
            process_docx_inplace(input_path, output_file)
            print(f'处理完成:{os.path.basename(input_path)} -> {output_file}')
        elif os.path.isdir(input_path):
            # 文件夹
            if not os.path.exists(output_path):
                os.makedirs(output_path)
            for filename in os.listdir(input_path):
                if filename.endswith('.docx'):
                    full_input = os.path.join(input_path, filename)
                    full_output = os.path.join(output_path, filename.replace('.docx', '_已处理.docx'))
                    process_docx_inplace(full_input, full_output)
                    print(f'处理完成:{filename}')
        else:
            print("输入路径不存在")
    
    
    if __name__ == '__main__':
        # ===== 使用示例 =====
        # 1. 处理单个文件,输出到指定路径
        input_path = r'C:Desktop读书笔记讲义'
        output_path = r'C:Desktop读书笔记讲义'
        process_file_or_folder(input_path, output_path)

    到此这篇关于Python文档处理之实现自动删除Word中带指定底纹颜色的内容的文章就介绍到这了,更多相关Python Word文档处理内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Python处理Word文档中的批注(添加、删除)
    • 使用Python在Word文档中添加,删除和回复批注
    • Python实现在Word中创建,读取和删除列表详解
    • Python在Word中进行图片添加、替换和删除操作
    • 使用Python实现在Word中添加或删除超链接
    • 通过Python实现在Word中添加和删除书签的操作
    • 详解如何利用Python代码删除Word文档空白行

    站内搜索