python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python Word文档处理

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

作者:够好了吗?

这篇文章主要为大家介绍了一个Python脚本,可以用于自动删除 Word 文档中带有指定底纹颜色的解析内容,文中的示例代码讲解详细,有需要的小伙伴可以了解下

代码功能概述

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

脚本支持两种输入模式:

文档内容示例

脚本代码 

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文档处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文