20252302 2025-2026-2 《Python程序设计》实验4报告

20252302 2025-2026-2 《Python程序设计》实验4报告

课程:《Python程序设计》
班级: 2523
姓名: 邢城瑜
学号:20252302
实验教师:王志强
实验日期:2026年6月13日
必修/选修: 公选课

一、实验内容

自动化公文格式检测程序(公文标准采用DKY公文格式)

二、实验分析

公文需要严格遵照公文格式,但公文格式条目较多,检查起来费时费力(还容易出错),我希望制作一个公文格式检测程序,检测现有docx公文是否符合公文格式,以节省人工反复校验的时间。
同时,公文校验相对比较简单,只要学习python-docx API相关知识和部分XML的知识即可,无需像网络渗透工具一样精通网络、通信等各领域知识,更适合人工实现。
本实验设计思路以及命令行工具由人类实现(好像叫什么邢城瑜),GUI由大模型实现。

三、实验设计

公文格式有许多条要求,其中部分功能较难实现。为此需要明确各格式校验路径,再判断是否在编写能力范围内、是否必要。

3.1 功能实现的依赖

构想以使用python-docx API为主,直接使用XML为辅

3.2 功能分类

(参考:公文要求(ver2025).docx,在作业zip中)
预想实现功能从具体类别上可以分为以下四类:页面设置、标题设置、正文设置、表格设置,
通过了解python-docx和XML现成功能,可讲所有小功能从实现方式上分为以下四类:

1.能直接调用python-docx实现的,非常简单

这里包含页面设置(上下左右边距)、大标题与正文的部分设置(字号、对齐方式、行间距、段前段后间距、文本前后缩进、首行缩进)、表格中的部分设置(字号、行距)

2.需深入到XML实现

各部分字体、字符间距,表格中的水平/垂直对齐

3.python-docx和XML结合实现

各级标题实现

4.不易实现,暂时跳过

上下文极其复杂类:标题上空2行下空1行、附件格式、落款格式
实现极其繁琐:表格行高、特殊标点、表格内两字词空格

各功能实现思路

Document()读入文件->识别不同信息分别为页面设置、标题设置、正文设置、表格设置并四个函数(check_page_margins()check_title()check_body_paragraphs()check_tables())分别进行处理。每一函数内部对于需要用不同方式(python-docx OR XML)处理的要素就分别处理即可,最终print_report()打印报告

                        ┌─────────────────────────────────────┐
                        │        全部待检查功能 (36项)          │
                        └─────────────────┬───────────────────┘
                                          │
    ┌─────────────┬───────────────────────┼───────────────────┬
    ▼             ▼                       ▼                   ▼              
┌──────────┐ ┌────────────┐          ┌──────────┐        ┌───────────────────┐   
│ 直接调用  │ │ 深入XML    │          │  API+XML │        │  暂时不实现的功能  │   
│python-docx│ │  实现      │          │  结合    │        │           │  
│  (16项)   │ │  (8项)     │          │  (1项)   │        │                  │  
└─────┬─────┘ └─────┬─────┘          └─────┬─────┘        └─────┬───────────┘  
      │             │                     │                    │
      ▼             ▼                     ▼                    ▼
┌────────────┐ ┌────────────┐      ┌────────────┐      ┌────────────────────┐
│ 页面边距4项 │ │ 各级字体6项 │      │ 各级标题    │      │ 上下文过于复杂      │
│ 标题字号   │ │ 字符间距2项  │      │ 字体+字号   │      │  标题空行/附件/落款 │
│ 正文字号   │ │             │      │ 识别与检查  │      │                    │
│ 对齐方式3项│ │ 表格对齐3项  │      └────────────┘      │ 实现过于繁琐        │
│ 行间距3项  │ │             │                          │  表格行高/特殊标点  │
│ 段间距3项  │ │             │                          │  两字空格           │
│ 缩进4项    │ │             │                          └────────────────────┘
│ 表格字号   │ │             │                         
│ 表格行距   │ │             │                         
└────────────┘ └────────────┘                          

API直接拿 (16项):                    XML挖 (8项):              API+XML (1项):
  例: pf.alignment → 居中              例: get_cn_font()       例: 各级标题
      pf.line_spacing → Pt(29)            → rFonts.eastAsia        → get_cn_font取字体类型
      section.top_margin → Cm(3.6)        get_latin_font()         → run.font.size取字号
                                          → rFonts.ascii/hAnsi     → 字体+字号联合判断角色
                                      get_char_spacing()
                                        → spacing.val / 20
                                      get_table_horizontal_align()
                                        → tblPr.jc.val
                                      get_cell_vertical_align()
                                        → tcPr.vAlign
                                      _is_in_table()
                                        → 沿XML树爬祖先

四、实现过程

代码分层设计概览

自上而下:上层可调用下层,下层不调上层
同级可互调

┌──────────────────────────────────────────────────────────────────┐
│  第七层 入口层 (main)                      行714-734  1个函数     │
├──────────────────────────────────────────────────────────────────┤
│  第六层 报告输出层 (print_report)          行668-708  1个函数     │
├──────────────────────────────────────────────────────────────────┤
│  第五层 调度层 (check_document)            行646-662  1个函数     │
├──────────────────────────────────────────────────────────────────┤
│  第四层 四大检查层                         行207-640  4个函数     │
│    check_page_margins  check_title                               │
│    check_body_paragraphs  check_tables                           │
├──────────────────────────────────────────────────────────────────┤
│  第三层 正文单项检查层                      行470-537  8个函数    │
│    _check_body_cn_font  _check_body_latin_font                   │
│    _check_body_size     _check_body_alignment                    │
│    _check_body_first_line  _check_body_line_spacing               │
│    _check_body_spacing  _check_body_indent                       │
├──────────────────────────────────────────────────────────────────┤
│  第二层 结果数据层                          行183-201  2个方法    │
│    CheckResult  CheckReport.add / summary                        │
├──────────────────────────────────────────────────────────────────┤
│  第一层 工具函数层                          行77-177  10个函数    │
│    字体挖掘: get_cn_font get_latin_font                          │
│    间距挖掘: get_char_spacing                                    │
│    单位转换: emu_to_cm  对齐映射: align_to_str                   │
│    表格属性: get_cell_vertical_align get_table_horizontal_align  │
│              has_text_wrapping                                   │
│    角色识别: _is_in_table  _find_title_para                      │
├──────────────────────────────────────────────────────────────────┤
│  第零层 常量层                              行26-70              │
│    页面边距  大标题标准  正文标准  标题标准  表格标准              │
└──────────────────────────────────────────────────────────────────┘

4.1 入口(读取文件)

命令行入口,输入路径以使用,做了一点错误提示,其中链接校验函数
image
校验函数,分别调用几个功能检查函数image

4.2 预写通用工具函数(用来挖数据)(提前写了避免后续重复写

4.2.1 XML挖属性

获取中文字体
image
获取西文字体类似,不再赘述
字符间距检查
image

4.2.2数据转化

emu转厘米
image
对齐样式转中文
image

4.2.3 表格归属类

单元格垂直对齐、表格水平对齐、表格文字环绕
image
判断段落是否在表格里image
_is_in_table(para)的逻辑说明:从当前段落出发向上爬,碰到<w:tbl>就说明在表格里,如果一直没找到就不在表格里。
设计这个函数的原因在于,不是所有段落都是正文。没有这个函数,表格里的所有段落都会被当成正文检查,然后报一大堆"表格内容仿宋小四不对(应为仿宋三号)"的误报。

4.3对每个段落确定其角色(标题?正文?表格内文字?)

image

4.4 分别写不同角色的对应函数

4.4.1 页面设置check_page_margins()

这部分最简单,直接调用python-docx写思路中预设的check_page_margins即可,利用API中section.xxx_margin直接拿,对比逻辑是简单的abs(实际 - Cm(3.6)) < Cm(0.05) (这里以上边距为例),留了一点容错
image

4.4.2 大标题设置check_title()

首先定位标题段落,然后再提取所有文字片段
image
之后分python-docx和XML两种类别分别实现不同要素(字体、间距等)的检验

python-docx实现的部分

字号实现,利用API中run.font.size(所有字号必须为二号(22),容差为一磅)image

对齐方式实现,利用API中pf.alignment
image

行间距实现,利用API中pf.line_spacing_rulepf.line_spacing(验证rule==EXACTLY且值约为Pt(29))
image

段前段后实现,利用API中pf.space_beforepf.space_after,这里特意做了None保护
image

前后缩进实现,利用API中pf.left_indentpf.right_indent,还经过预写函数emu_to_cm进行格式转换,设置容差为0.1cm
image

首行缩进实现,利用API中pf.first_line_indent和上面的预写函数emu_to_cm实现
image
字符间距实现,值必须为None(未设置)或者0
image

XML实现部分

中文字体
调用预写工具函数get_cn_font,然后逐个检查
image
西文字体同理,不再赘述。

4.4.3正文设置check_body_paragraphs()

思路和4.4.2的标题大致相同,先定位,然后调用八个三项函数分别检验字体、字号、对齐等要素,分别输出检查结果
image
由于代码简单且思路与4.4.2中的几个单向函数思路重复,为重复性工作,故这里不再详细放出八个单项函数。

4.4.4 表格check_tables()

基本逻辑一致,筛选出对应数据为表格后分别调用水平对齐函数get_table_horizontal_align(table)、文字环绕函数has_text_wrapping(table)和垂直居中函数get_cell_vertical_align(cell),对于单元格内内容,调整字体字号和行距即可。
image
image

4.5 LLM生成GUI

模型使用deeepseekV4 pro
生成GUI,

五、实现结果

最终完成了一个命令行工具(手搓)和一个对应的GUI(deepseek),可以初步检测docx类型文档是否符合公文格式

5.1 命令行工具(Powered by XCY)

在终端中输入python Format_Checker.py并按提示手动输入被检测文件的路径即可
测试样例:一个正常的不完美的docx文件
image
测试成功嘿嘿嘿

5.2 GUI工具(made by DeepseekV4pro)

GUI工具可以通过“浏览”来找寻文件,无需手动寻找路径(但是需要手动浏览,但还是方便多了),同时还可以导出txt形式的报告
界面如下
image
测试文档:
image
导出报告:
image

六、实验中遇到的困难与解决、实验收获

困难与解决

1.中文字体读不出来,遇到中文时run.font.name 永远只返回 'Times New Roman',原来word把中文字体单独存在w:eastAsia,英文存在w:ascii,python默认只读英文的那个
解决:发现run._element能进底层XML,一层层往下找w:rPr → w:rFonts,再 .get('w:eastAsia')才拿到中文字体
这说明python-docx库的封装也可能有问题,可能需要人工处理(百行代码消耗一个鸡蛋糕
2.程序莫名其妙崩溃
人工校验没发现,然后扔给AI校验一下,发现是对None的逻辑问题,pf.space_before.pt 报了 AttributeError:NoneType。我的判断逻辑是"None算通过",但写报错信息时没想过它可能是None,直接 .pt 了
解决:在每个对应的执行前加了一个判断,如果是None直接输出‘未设置’而不是直接崩溃。()
3.旧版代码中表格段落被按照正文处理。
发现原因:没有正确定位哪些段落在表格中、哪些是真正的正文段落。
解决:python-docx的Paragraph对象没有直接判断的接口,询问AI后明白修正思路:通过检索<w:tbl>来判断是否在表格中。

实验收获

1.第三方API不一定全,如果用不了就只能手动编写。
2.需要养成良好的封装习惯,在本实验中体现为任何拿到的值都得先看是不是None,否则可能出现“点了一碗炒饭然后程序炸了”的情况。
3.校验类工具难点不在校验而在于繁琐的分类。

七、课程总结、感想体会与建议

课程总结

强哥教的Python课覆盖以下知识点:简单语法、序列、函数、字符串、异常处理、调试、socket通信、简单爬虫等。其中,部分知识点做了实验,完成了简易计算器、简易猜测游戏等简单程序,还有一些略有实用性的socket通信、敏感词过滤等工具。在这些工具编写中,python的“轻量化”体现得淋漓尽致:字少。
分几个我印象深刻的知识点来说:
初识python时“蛋炒饭盖浇饭”的比喻让当时只学过C语言的我对不同语言之间的分类有了形象的理解
类与对象的一课“水果”和具体水果的比喻让我明白了python语言中类与对象的方便
socket通信实验中顺便了解了通信相关知识(还不小心因为没关防火墙闹了笑话
总体来讲,课程内容丰富,强哥讲解诙谐幽默,很有个人魅力。

课程感悟

当初选这门课时,是在学CTF过程中发现还是需要掌握一些简单的脚本技能,而这些脚本大多都是python写的,这些脚本可以节省大量时间,便因此报了强哥久享盛誉的python课,也确实学到了不少东西,例如socket通信、爬虫,这些都是在大一上的C语言中没有接触过的东西,让我真正感受到技术应用到实际的落地的安心感。但一学期学下来,总有一种越学不会的东西越多的感觉,说明自己还是有很多很多需要了解的吧。
本次选题是基于我日常干学生工作时的实际需求(人工机械校对挺耗精力的)。
本次综合实验也把我之前很多学的东西串了起来,而且做成一个小项目还挺有成就感的。

课程建议

总体来讲课程节奏和内容充实度适中,形象生动、风趣幽默,看来学长学姐没推荐错~
至于建议,可以适当增加“边带着敲代码边讲解”的教学方式比重,感觉对于学时不算太多的晚课,在提升学生能力上还是挺有用的。

posted @ 2026-06-19 16:50  Jade2000  阅读(2)  评论(0)    收藏  举报