测试工程师该如何清理需求文档

在需求文档清理过程中,有时需要根据预先配置的关键词列表,过滤掉标题中包含某些特定关键元素的段落内容。例如,用户可能希望忽略某些章节或段落(如 “附录”、“参考文献”)中的内容。为实现这一需求,我们可以扩展现有的文档清理工具,通过配置关键词列表,自动过滤掉标题中包含这些关键词的段落。


功能实现

以下是功能的实现步骤:

  1. 预先配置关键词列表:定义一个关键词列表,包含需要过滤的关键元素。
  2. 检查标题是否包含关键词:遍历文档内容,判断标题是否匹配关键词列表中的任何元素。
  3. 过滤段落内容:当标题匹配过滤条件时,跳过该标题及其正文段落。
  4. 保持其余内容完整提取:只保留未匹配过滤条件的内容。

在需求文档中,标题的格式可能不固定,例如:

  • 标题可能是数字开头(“1. 概述”、“4.1 功能描述”)。
  • 标题可能是纯文本(“功能要求”、“附录A”)。
  • 标题可能包含特殊字符(“4 - 功能描述”、“附录 A - 参考资料”)。
  • 部分标题没有明显的层级标记。

为了更通用地判断和提取标题,我们可以设计一种多规则的匹配方法,结合以下特征来判断段落是否为标题:

  1. 标题特征分析:通过段落的样式、文本内容和格式特征判断标题。
  2. 关键词匹配:通过预配置的关键词列表快速判断是否为标题。
  3. 结合正则表达式:适配多种标题格式(如数字开头、带层级标记、纯文本标题)。

以下是实现通用标题判断和内容过滤的完整方案。


方案设计

标题判断规则

  1. 样式判断

    • 在 Word 文档中,标题通常使用特定的样式(如 “Heading 1”, “Heading 2”)。
    • 如果文档结构清晰,可以通过样式直接判断标题。
  2. 正则表达式匹配

    • 数字开头的标题:^\d+(\.\d+)*\s+.*
      • 示例:1. 概述4.1 功能描述
    • 带层级标记的标题:^\d+[-]\d+\s+.*
      • 示例:4-1 功能描述
    • 纯文本标题:^(附录|参考文献|功能要求|概述).*$
      • 示例:附录A功能要求
  3. 关键词匹配

    • 如果标题中包含指定的关键词(如 “附录”、“参考文献”),直接判断为标题。

实现代码

以下代码实现了通用标题判断和基于标题过滤内容的功能。

代码实现

import re
from docx import Document

def is_title(paragraph, filter_list=None):
    """
    判断段落是否为标题
    :param paragraph: 段落对象
    :param filter_list: 预配置的关键词列表(可选)
    :return: 是否为标题(True/False)
    """
    # 获取段落文本
    text = paragraph.text.strip()

    # 空段落不可能是标题
    if not text:
        return False

    # 样式判断(适用于规范化文档)
    if paragraph.style.name.startswith("Heading"):
        return True

    # 正则表达式匹配标题格式
    if re.match(r"^\d+(\.\d+)*\s+.*", text):  # 数字开头的标题
        return True
    if re.match(r"^\d+[-]\d+\s+.*", text):  # 带 "-" 的标题
        return True
    if re.match(r"^(附录|参考文献|功能要求|概述).*$", text):  # 特定关键词的标题
        return True

    # 关键词匹配(如果提供了过滤关键词列表)
    if filter_list and any(keyword in text for keyword in filter_list):
        return True

    # 默认不是标题
    return False


def filter_content_by_title(docx_path, filter_list):
    """
    根据标题中的关键词过滤段落内容
    :param docx_path: docx 文件路径
    :param filter_list: 预先配置的关键词列表
    :return: 过滤后的文档内容
    """
    doc = Document(docx_path)
    filtered_content = []
    skip_section = False  # 用于标记是否跳过当前段落内容

    for paragraph in doc.paragraphs:
        text = paragraph.text.strip()

        # 判断是否是标题
        if is_title(paragraph, filter_list):
            # 如果标题中包含过滤列表中的关键词,跳过该段落
            if any(keyword in text for keyword in filter_list):
                skip_section = True
                continue
            else:
                skip_section = False

        # 如果当前段落不属于需要过滤的章节,则保留
        if not skip_section and text:
            filtered_content.append(text)

    return "\n".join(filtered_content)


# 示例调用
docx_path = "需求文档.docx"

# 配置要过滤的标题关键词列表
filter_list = ["附录", "参考文献", "声明"]

# 调用函数过滤内容
filtered_text = filter_content_by_title(docx_path, filter_list)

# 打印过滤后的内容
print("过滤后的文档内容:")
print(filtered_text)

代码解析

  1. is_title 函数

    • 样式判断:如果段落的样式名称包含 “Heading”,直接判断为标题。
    • 正则表达式匹配:适配多种标题格式,包括数字开头的标题、带 “-” 的标题和特定关键词的标题。
    • 关键词判断:如果标题包含过滤列表中的关键词(如 “附录”、“参考文献”),也判断为标题。
  2. filter_content_by_title 函数

    • 遍历文档段落,使用 is_title 判断段落是否为标题。
    • 如果标题中包含过滤关键词,跳过该标题及其正文段落内容。
    • 将未过滤的段落内容保存到结果中。
  3. 预先配置的关键词列表

    • 用户可以通过 filter_list 配置需要过滤的关键元素,例如 ["附录", "参考文献", "声明"]
    • 这些关键词将用作标题过滤的条件。
  4. 标题匹配规则

    • 假设标题格式为 数字.数字 标题(如 4.1 功能描述)。
    • 使用正则表达式 ^\d+(\.\d+)*\s+.+ 匹配标题格式。
  5. 跳过过滤段落

    • 如果标题中包含任一关键词,则设置 skip_section = True,跳过该标题及其正文内容。
    • 直到遇到下一个非过滤标题时,停止跳过。
  6. 保留其余内容

    • 对于未匹配过滤条件的段落,将其内容追加到结果中。

微调方法

1. 更灵活的标题匹配规则

如果文档中的标题格式不固定,可以调整正则表达式,适配更多标题样式。例如:

  • 支持 数字-数字 标题 格式:
    re.match(r"^\d+(-\d+)*\s+.+", text)
    
  • 支持仅包含关键字的标题(如 附录参考文献):
    if any(keyword in text for keyword in filter_list):
    

2. 动态加载过滤列表

可以将过滤列表存储在外部配置文件(如 JSON 文件)中,方便用户动态调整。例如:

import json

def load_filter_list(config_path="filter_config.json"):
    """
    从配置文件加载过滤关键词列表
    :param config_path: 配置文件路径
    :return: 关键词列表
    """
    try:
        with open(config_path, "r", encoding="utf-8") as file:
            return json.load(file).get("filter_list", [])
    except FileNotFoundError:
        print(f"配置文件 {config_path} 未找到,使用默认过滤列表。")
        return []

# 示例配置文件内容:
# {
#     "filter_list": ["附录", "参考文献", "声明"]
# }
filter_list = load_filter_list("filter_config.json")

3. 高亮匹配的标题(调试功能)

为了调试过滤逻辑,可以输出匹配到的标题列表,方便用户验证。例如:

matched_titles = []

for paragraph in doc.paragraphs:
    text = paragraph.text.strip()
    if re.match(r"^\d+(\.\d+)*\s+.+", text):
        if any(keyword in text for keyword in filter_list):
            matched_titles.append(text)

print("匹配到的标题:")
print("\n".join(matched_titles))

4. 结合表格和图片的过滤

如果需要同时过滤标题中的表格和图片,可以扩展逻辑,检查表格和图片是否属于被过滤的章节。例如:

for paragraph in doc.paragraphs:
    text = paragraph.text.strip()
    if re.match(r"^\d+(\.\d+)*\s+.+", text):
        if any(keyword in text for keyword in filter_list):
            skip_section = True
            continue
        else:
            skip_section = False

    # 跳过属于被过滤章节的表格和图片
    if not skip_section:
        # 处理表格和图片
        ...

功能测试

测试案例

测试文档内容

1. 概述
这是文档的概述部分。

2. 功能要求
2.1 功能描述
这是功能描述的内容。

附录A
这是附录的内容,不需要提取。

3. 技术要求
这是技术要求部分。

参考文献
这是参考文献部分,不需要提取。

测试结果

过滤关键词列表

filter_list = ["附录", "参考文献"]

过滤后的结果

1. 概述
这是文档的概述部分。

2. 功能要求
2.1 功能描述
这是功能描述的内容。

3. 技术要求
这是技术要求部分。

功能扩展

1. 动态调整标题规则

为了适应更多标题样式,可以动态调整标题匹配规则。例如:

  • 增加对小标题的支持(如 “功能描述”)。
  • 支持标题后面带特殊标记(如 “4.1 功能描述(重要)”)。

修改代码如下:

# 支持标题后带特殊标记
if re.match(r"^\d+(\.\d+)*\s+.*[\((].*[\))]$", text):  # 示例:4.1 功能描述(重要)
    return True

2. 输出过滤结果

将过滤后的内容导出为 txtjson 或其他格式,便于进一步处理。

# 导出为 TXT 文件
with open("filtered_content.txt", "w", encoding="utf-8") as file:
    file.write(filtered_text)

# 导出为 JSON 文件
import json
with open("filtered_content.json", "w", encoding="utf-8") as file:
    json.dump({"content": filtered_text}, file, ensure_ascii=False, indent=4)

3. GUI 集成

将标题过滤功能集成到图形用户界面(GUI),允许用户动态输入过滤关键词和调整匹配规则。

示例代码(PyQt5):
from PyQt5.QtWidgets import QLineEdit, QPushButton, QTextEdit, QVBoxLayout, QMainWindow, QApplication

class FilterContentApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("文档内容过滤工具")
        self.setGeometry(100, 100, 600, 400)
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        # 输入过滤关键词
        self.filter_input = QLineEdit(self)
        self.filter_input.setPlaceholderText("请输入过滤关键词(用逗号分隔)")
        layout.addWidget(self.filter_input)

        # 显示过滤后的内容
        self.result_display = QTextEdit(self)
        layout.addWidget(self.result_display)

        # 按钮:开始过滤
        filter_button = QPushButton("开始过滤", self)
        filter_button.clicked.connect(self.filter_content)
        layout.addWidget(filter_button)

        # 设置窗口布局
        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def filter_content(self):
        # 获取用户输入的关键词
        filter_list = self.filter_input.text().split(",")
        docx_path = "需求文档.docx"

        # 调用过滤函数
        filtered_text = filter_content_by_title(docx_path, filter_list)

        # 显示结果
        self.result_display.setPlainText(filtered_text)


# 主程序入口
if __name__ == "__main__":
    app = QApplication([])
    window = FilterContentApp()
    window.show()
    app.exec_()

总结

通过通用标题判断方法,我们能够适配格式不固定的标题,动态过滤需求文档中的无用内容。结合强大的正则表达式匹配和关键词判断逻辑,工具可以高效处理多种文档结构,满足各种复杂场景需求。添加基于预先配置列表的标题过滤功能,我们能够高效跳过需求文档中指定章节或段落的内容。结合灵活的正则匹配规则和 GUI 集成,该功能可以满足用户的多样化需求,并显著提升文档清理工具的实用性和智能化水平。

你可能感兴趣的:(测试提效,python,python,需求分析)